MarinhoBrandão.com
"O risco que se corre ao se introduzir novas tecnologias é menor do que aquele que se corre ao não introduzi-las." ;)

Nova versão do site

Publicado por marinho, há 1 ano, 8 meses | django google python

Ao meio-dia do dia 19 eu atualizei este site mais uma vez, com algumas novidades que vinham sendo feitas em doses homeopáticas havia bastante tempo. Seguem abaixo os motivos e meios de como isso aconteceu e quem sabe você possa também aproveitar dessa experiência.

Mais social

http://www.marinhobrandao.com/media/uploads/gallery-file/community_1.jpg

O primeiro motivo que me levou a querer mudar o meu site pessoal foi torná-lo mais social. Isso é porque a versão antiga não fazia sequer menção ao livro Aprendendo Django no Planeta Terra, ao meu Twitter ou a nenhum de meus espaços em redes sociais.

Numa Internet cada vez mais social, nerds como eu costumam participar de vários canais ao mesmo tempo, trocando ideias e publicando conteúdo em diferentes lugares, e isso cria um problema crescente: juntar tudo isso num só lugar para que pessoas que acompanham o meu trabalho possam de fato fazê-lo.

Isso já não é mais um problema só de geeks. É cada vez mais real para empresas e profissionais que participam ativamente da Web 2.0 (ou queiram fazê-lo).

Grande parte dos serviços que usamos, como Twitter, Picasa, Flickr, etc. oferecem widgets para integrar em sites, mas o preço que se paga é ter uma caixa completamente diferente do restante do layout, sendo carregada via JavaScript e com propagandas indesejadas.

Solução rápida: RSS - quando disponível - ou apenas links para casos menos importantes.

Para isso eu criei um código [10], cuja função deve ser adicionada à setting TEMPLATE_CONTEXT_PROCESSORS.

As constantes TWITTER_URL e PICASA_URL devem adaptadas para cada caso. No caso do Twitter a URL é a fornecida como RSS da sua conta, e no caso do Picasa, basta trocar ‘marinho’ pelo ID da conta e o número após ‘albumid’ deve ser trocado pelo album que você desejar (ou simplesmente remover a string ‘albumid/NUMERO’ para visualizar todas as fotos da conta.

Observe que tudo em feito em modo Lazy, ou seja, só é carregado quando necessário, armazenado em cache, que expira em 1800 segundos (30 minutos).

Casos onde eu queria apenas linkar (por ora) bastou criar a seção /social/ e pronto :)

Saindo do Google App Engine

http://www.marinhobrandao.com/media/uploads/gallery-file/the-godfather.jpg

Outro motivo bastante considerado foi tirar o site do Google App Engine.

O serviço de hospedagem do Google não tem tido o mesmo desempenho de antes, especialmente para imagens, e isso vinha me incomodando. Junta-se a isso o fato de erros obscuros ocorrerem de vez em quando sem nenhum motivo aparente e a solução também aparecer 2 dias depois sem explicações e você tem mais um motivo considerável.

Aí vem aquele incômodo crescente coma dependência do Google que eu cultivei ao longo dos anos, os constantes ataques à minha conta pessoal no Gmail e foi um motivo real para começar a tirar algumas coisas de lá.

Migrando o código

Mas como migrar para o ORM do Django, sistema de cache e outras coisas?

O segredo foram os cuidados que tomei quando criei as aplicações. Diversas funções que um dia poderiam ser úteis no Django convencional foram feitas sob a égide do DRY, de forma que apenas algumas linhas fossem suficientes para adaptá-las. Sendo assim, funções de publicação de mensagens, envio de e-mails, decorators de templates, gravação de cache e outras funções foram facilmente convertidas.

Desta forma a adaptação do código-fonte se resumiu a ajustar o decorator de cache, mudar os nomes dos tipos de campos (ex.: db.StringProperty() para models.CharField(max_length=N, blank=True)).

Migrando os dados

Mas como você já deve ter imaginado, o maior problema não é o software, e sim os dados.

O BigTable é completamente incompatível com bancos relacionais, e o Google não disponibiliza nenhum serviço oficial de dumping.

Uma das soluções é o bulkloader [8], disponibilizado como parte do SDK. Para mim não atendeu pois eu queria uma solução mais rápida, sem precisar codificar mais.

Outra solução é o Gaebar [9], que faz a transferência dos dados de uma forma mais sutil, em pacotes pequenos, do servidor de produção para o servidor local, também não funcionou bem pra mim.

Então a solução que adotei foi gerar os dados em formato JSON e importá-los com outro código. Foi bastante simples e resolveu, mas esta solução não atende se o volume de dados for grande o bastante para exceder o limite de tempo da requisição que o Google App Engine permite.

Alternativa de hospedagem na cloud

Escolhi a Rackspace [11] para meu serviço de hospedagem predileto. Os custos estão bem mais baixos do que a concorrência, o desempenho tem superado a Amazon WS e Google App Engine de longe, e a facilidade de iniciar uma máquina virtual e começar a usar foi muito satisfatória.

O melhor custo/benefício que encontrei. Recomendo.

Atualização para Django 1.2

http://www.marinhobrandao.com/media/uploads/gallery-file/django-folder.jpg

A versão 1.2 do Django consagra o jQuery e o CSRF, suporta múltiplas conexões com o banco e corrige o velho sistema de mensagens, fora outras novidades.

É claro que alguns projetos que eu toco vão ter que esperar para migrar para a nova versão, mas já havia algum tempo que eu vinha atualizando a maioria deles, e não seria diferente neste caso. As mudanças não impactaram quase nada e bastou implementar o CSRF para ficar tudo ok.

Sendo assim, a implementação do CSRF se resume a duas coisas:

  1. Encapsular views sob o decorator @csrf_protect, assim:

    from django.views.decorators.csrf import csrf_protect
    ...
    @csrf_protect
    def minha_view(request):
        ...
    
  2. E no template, acrescentar o parametro de verificação, assim:

    {% csrf_token %}
    

Essa mudança reforça diretamente a segurança dos formulários contra ataques de requisições falsas de sites duvidosos.

Atualização para HTML5 e CSS3

http://www.marinhobrandao.com/media/uploads/gallery-file/html5-elvis.jpg

Nos próximos anos a Web vai respirar HTML5, e com ele vem junto o CSS3, as fontes OTF, o formato multimídia OGG, sessões de longa duração, WebSockets e assim por diante.

Como sabemos, o calo no pé dos desenvolvedores Web sempre foi e continua a ser o Internet Explorer. De acordo com este site [3] a versão 9.0 do I.E. ainda vai ser incompatível o bastante para incomodar e “freiar” caras como eu, que adoram novidades.

Mas eu decidi que esse não seria um empecílio.

Para começar, criei um fork [4] do django-html5 [5]. Este projeto implementa suporte aos novos inputs do HTML5, mas eu precisava de outro conjunto de funcionalidades, baseando na necessidade de detectar se o navegador do usuário é compatível com HTML5 e sendo assim, priorizar templates com extensão .html5 antes dos homônimos com extensão .html.

Desta forma, as funcionalidades que implementei permitiram que, ao detectar um navegador incompatível, o template antigo é renderizado e mostrado para o usuário.

Abrindo mão dos middlewares e decorators de cache do Django

Eu já havia comentado isso aqui, em outro artigo, mas eu melhorei bastante o decorator, que substitui o @cache_page, e tem o mesmo nome.

O conjunto de caching de requests do Django é um tanto incompatível com cache invalidation, e a solução que mais se aproximou de casar uma coisa com outra foi esta [1] e como podem ver, não foi das melhores.

Por isso eu implementei o meu próprio decorator [2] e o melhorei ao passar do tempo.

O decorator se baseia somente na URL e na compatibilidade do navegador com HTML5 para montar a chave do cache. O Django usa um hash do cabeçalho do HTTP, e é exatamente isso que torna complicado o processo de saber qual é a chave respectiva a uma determinada URL.

O decorator basicamente funciona da mesma forma que o do Django, mas ao criar a chave para gravar no cache, ele verifica se o navegador é compatível com HTML5 e acrescenta isso à chave.

Para forçar a o cache invalidation, basta saber a URL e chamar a função invalidate_cache. Desta forma, seu timeout de expiração pode ser de quanto tempo quiser, por exemplo: 24 horas, 10 dias, enfim. Se fizer direitinho o cache invalidation, o tempo de expiração pode ser o mais longo possível.

Template inspirado no Woo Irresistible

http://www.marinhobrandao.com/media/uploads/gallery-file/irresistible.jpg

Por fim, justiça seja feita. O layout foi criado com base no template Irresistible [6], da Woo Themes [7].

Fora isso, mantive a tradição do rosa, mas agora pegou uma cor mais escura, caminhando pro vinho. Gostei :) Referências externas