16 de novembro de 2010

Fixtures no Web2py

Uma das coisas boas dos frameworks modernos é trabalhar com fixtures.

Se você ainda não sabe, fixtures são a massa de dados inicial do seu banco de dados. Aqueles registros que você inclui só pra testar suas consultas, lembra? Pois é; são fixtures. E dá um trabalho danado incluir novamente toda vez que você precisa mudar alguma coisa no seu banco de dados, né? As fixtures estão aí pra ajudar exatamente nisso.

O esquema é o seguinte: você define um conjunto de dados inicial. Daí, toda vez que as tabelas são criadas, os dados são inseridos automaticamente, pra você não ter que popular tudo na mão novamente.

Isso te dá liberdade (e segurança) de apagar tudo e recomeçar sem sujeira nas tabelas. A qualquer momento você pode esvaziar ou recriar tudo. Sua massa de teste estará lá novamente. É como se fosse um "quick restore" dos seus dados.

Posso dizer que é uma mão na roda, mas é preciso tomar alguns cuidados para não se perder.

Eu usei fixtures pela primeira vez no Django e demorou um pouco até cair a ficha sobre como isso funciona no web2py. De tão fácil que é, às vezes a gente nem percebe.

Você pode trabalhar com fixtures no Web2py de 3 formas:
a) Incluindo as linhas via script que é executado automaticamente;
b) Importando de um arquivo CSV;
c) Mesclando as duas formas anteriores.

Os scripts do diretório my_app/models são executados em ordem alfabética sempre que sua aplicação é requisitada. Ou seja, a cada request. Portanto, ali é um bom lugar para colocar scripts que fazem alguma configuração ou preparação para sua aplicação rodar. Bem, as fixtures fazem exatamente isso, certo? Elas preparam a massa de dados de sua aplicação. Portanto, podemos iniciar as fixtures chamando-as a partir do script my_app/models/z_fixtures.py, por exemplo.

Nesse script, você pode incluir os dados iniciais se suas tabelas estiverem vazias, fazendo o seguinte teste:
if db(db.produtos.id>0).count() == 0:
    db.produtos.insert(codigo=1234, nome='martelo')
    db.produtos.insert(codigo=1235, nome='parafuso')
    db.commit()

Fazendo isso para todas as tabelas, você terá seus dados recarregados sempre que esvaziá-las.
A vantagem desse método é que você tem total domínio sobre a forma de inclusão dos dados. A desvantagem é que escreve muito código.

A outra forma de trabalhar com fixtures, é usando o appadmin (my_app/appadmin) para inserir os dados e usar a opção "exportar para csv", que tem na view de listagem dos dados.

A vantagem desse método é que você garante a inclusão de dados que passaram pelos validadores definidos e aproveita a exportação para csv que já vem com o Web2py.
Uma desvantagem é que você vai ter que importar os dados na mão sempre que suas tabelas forem zeradas. A outra é que, dependendo da mexida nas tabelas, suas fixtures podem não carregar por diferença de layout.

Mas, será que existe uma maneira de aproveitar e unir as duas formas abordadas? Sim, claro. O Web2py é flexível e praticamente tudo que é possível fazer pelo appadmin, também é possível fazer via programação.

Então, sugiro você usar o appadmin para inserir os dados, exportá-los para csv pelo próprio appadmin e o método db.minha_tabela.import_from_csv_file() no script my_app/models/z_fixtures.py para importar os dados, se a tabela estiver vazia.

Aproveite e veja os métodos para importar/exportar um banco de dados inteiro. Isso pode te ajudar bastante.

Experimente. Use fixtures e você verá como sua vida fica mais fácil e produtiva.

8 de novembro de 2010

request.now ou datetime.now?

O Web2py tem a variável request.now que você pode usar no lugar de datetime.datetime.now() sem precisar importar nada. Essa variável guarda o horário que a requisição foi executada.

Eu estou fazendo uma aplicação com uma parte rodando via cron e me deparei com uma situação inusitada: todos os registros alterados no processo da cron tinham o mesmo horário de modificação. Isso porque eu usei o update=request.now na definição do campo que guarda a hora da última modificação do registro.

A situação é que, no shell (cron), a requisição ocorre apenas uma vez, no momento que ele é iniciado. Já na web, a requisição ocorre toda vez que uma URL é solicitada pelo browser. Como no shell a característica é executar processos em background, não existe a URL sendo solicitada. Na web, a cada clique de link ou de botão, uma nova requisição é realizada.

Então, o request.now, na verdade, contém o horário que a requisição iniciou.

Para resolver meu problema, eu passei a usar o update=datetime.datetime.now(). Conferindo os resultados depois dessa modificação, me deparei com o mesmo problema: todos os registros alterados pelo processo da cron com o mesmo horário de modificação.

Recorri à lista mundial do web2py e aprendi que esses valores para default e update são avaliados apenas no momento que os models são executados, quando associados a conteúdos fixos ou variáveis.

Para resolver o problema, temos que usar lambda assim: update=lambda:datetime.datetime.now(). Dessa forma, como temos a chamada de uma função (lambda no nosso caso), toda vez que um registro for modificado, esse conteúdo do update será reavaliado.

O mesmo vale para a propriedade default.

Portanto, use os parâmetros default e update com lambda, para que atualizem o conteúdo no momento de inserção/alteração do registro.

Segue um exemplo:

from datetime import datetime
db.define_table('ficha',
    Field('nome', 'string'),
    Field('quando', 'datetime', default=lambda:datetime.now())

29 de outubro de 2010

print vai pra console

Volta e meia precisamos depurar programas, principalmente quando o negócio do aplicativo é complexo ou quando estamos aprendendo uma tecnologia nova, pra ver como ela funciona.

No Web2py você pode depurar sua aplicação web sem interferir no resultado das suas páginas.

Se você usar o comando print do Python, o conteúdo printado sai na console do Web2py, ao invés de ser mostrado no browser.

Faça um teste e veja como funciona. Com isso você consegue entender melhor a sequência de eventos do Web2py e depurar sua aplicação.

Fica a dica.

22 de outubro de 2010

Markmin pronto pra usar

Se você já precisou permitir que os usuários do seu aplicativo inserissem conteúdo para ser mostrado, provavelmente pensou na alternativa de usar alguma linguagem de marcação que não fosse HTML.

A Wikipedia popularizou isso, e hoje temos várias por aí. Quase todas têm certa semelhança, mas o importante é que seu usuário não precisa estudar HTML para usar seu aplicativo.

O problema em alguns ambientes é fazer seu aplicativo entender isso e converter a linguagem de marcação em HTML para o browser mostrar.

O Web2py traz o Markmin, uma linguagem de marcação bem simples, que resolve a maioria dos seus problemas. E o melhor: é facinho de usar.

Bem, não vou ficar escrevendo muito. Veja: o Markmin no Web2py.

Layouts prontos

Quem me conhece sabe que fazer layout não é o meu forte. Eu não tenho o menor dom para fazer um layout bonitinho, pelo menos.

Agora meus problemas praticamente acabaram!
Temos plugins que possibilitam usar layouts do CSS Zen Garden e do Free CSS Templates no Web2py:
  1. CSS Ocean Garden
  2. Free CSS Templates Plugin
Tá, mas se você tem algum dom para bolar layouts legais, qual a vantagem disso?

A maior delas é que você não precisa partir do zero.
A outra é que esses layouts são table less, o que te dá uma grande vantagem para ajustá-los às suas necessidades.

Escolha, baixe e use. ;-)

Web2py app wizard

Quando que você for desenvolver uma nova aplicação no Web2py, é boa prática iniciar com o esqueleto que ele gera a partir da aplicação examples.

Já tem alguma coisa pronta ali.
Mas se você é daqueles que gostam de ver mais recursos e achava que essa aplicação inicial era muito "pelada", dá uma olhada nesse screecast que demonstra o Web2py Application Wizard.

Não sei se você reparou, mas ele gera até dados de teste nas tabelas! E a aplicação do layout? Viu só?

Na data de postagem desse artigo ele ainda estava em beta. Vamos aguardar e ver como vai ficar quando lançar oficialmente.

20 de outubro de 2010

web2py no shell do Python

Muita gente deve saber, mas não todos: é possível usar o web2py apenas com o shell do Python.

Eu vi isso no Django e gostei muito, pois tira proveito do jeito pythônico de aprender com pequenos testes.

Faça assim: $ python web2py.py -S aplicacao -M

O parâmetro -S aplicacao informa qual aplicação você vai usar no shell.
Já o -M faz com que os models sejam executados ao iniciar o shell.

Qual a vantagem disso? Bem, você pode brincar com o DAL, por exemplo, sem fazer programas.

Para saber mais (muito mais), leia o artigo Shell Only Web2py escrito pelo Massimo di Pierro, criador do web2py.

(dica do @rochacbruno, um dos brasileiros que contribuem com o web2py)

8 de junho de 2010

Rodando o web2py no seu computador

Se você nunca viu o web2py na vida, continue lendo esse post. Aqui vamos iniciar com o web2py de uma forma bem iniciante mesmo.

O primeiro passo é fazer download do web2py em web2py.com

A praticidade começa logo de cara. Para executá-lo, basta baixar o pacote para seu sistema operacional e começar a usá-lo. Simples e direto, como tudo deveria ser.

Vale notar as versões de Python com as quais o web2py trabalha. Na época da escrita desse post, junho/2010, a versão corrente do web2py era a 1.79.1. Confira na página de download se sua versão de Python é compatível e faça essa adequação, caso necessário.

A seção 3.1 do livro oficial de web2py, escrito pelo autor do framework, trata de como iniciar o web2py, com instruções para as plataformas Windows, Linux e Mac OS X. Por isso não vou entrar em detalhes aqui. Vou apenas dizer que ao executar o web2py, você está colocando no ar um mini-servidor web, que serve para o desenvolvimento de suas aplicações.

O Django e o Ruby on Rails têm a mesma funcionalidade e filosofia: iniciar o quanto antes, sem complicações. Não precisa configurar Apache, como no PHP.

O servidor web2py (como vamos chamá-lo aqui) roda por default em http://localhost:8000.
Na verdade, além de ser um mini-servidor web, ele é uma interface administrativa para suas aplicações. É diferente do Django porque aqui no web2py, você pode criar aplicações, escrever programas, views ou modelos de banco de dados sem usar um editor externo. É uma forma de editar aplicações pelo browser. O Django fornece um admin muito poderoso, mas apenas para as tabelas do banco de dados, não para sua aplicação propriamente dita.

Antes de iniciar o servidor web2py, você precisa informar uma password de administrador para controlar as aplicações locais. Faça isso e o servidor será iniciado, mostrando a página da aplicação default, que é chamada de "Welcome".

A aplicação Welcome é muito simples, mas já podemos ver algumas boas funcionalidades do web2py em ação. Se você a viu em português, abra a pasta web2py/applications/welcome/languages e renomeie os arquivos pt.py, pt_br.py e pt_pt.py, dê refresh na página e ela aparecerá em inglês para você.

Sugiro que você abra um desses arquivos de idiomas e também o arquivo web2py/applications/welcome/views/default/index.html

O helper T() que está no index.html é o que faz com que o texto traduzido seja buscado. Faça alguns testes modificando algumas traduções, salvando o arquivo de idiomas e dando refresh na página. A tradução é feita na hora, sem adição de módulos externos. Já está lá embutida no web2py. É tão simples, que a aplicação que serve de apresentação do framework já tem isso nela funcionando.

Lembra que eu falei que o web2py permite que você edite sua aplicação diretamente pelo browser? Então vamos modificar os arquivos de tradução usando-o, seguindo os seguintes passos:
  1. Na página principal da app Welcome, em inglês, clique no link "click here for the administrative interface".
  2. Digite a senha de administrador que você informou ao iniciar o servidor web2py e clique no botão login.
  3. Escolha o link "EDIT" que está abaixo do nome da aplicação welcome.
  4. Role a página até aparecer a seção "Languages".
  5. Clique na opção "edit" ao lado do arquivo de idioma que você quer modificar.
  6. Traduza o que quiser e clique no botão "update", ao final da página.
Essa é apenas uma introdução rápida ao web2py. Brinque um pouco com ele, dê uma lida no manual online que está disponível na homepage do web2py.

E vamos trocando ideias.