Vindo de mim, um elogio ao web2py pode parecer tendencioso, já que sou um dos desenvolvedores do framework. Porém uma coisa que me fascinou, mesmo antes de me tornar desenvolvedor, foi a implementação da camada de apresentação (views, do modelo MVC).
No web2py a camada de apresentação é parecida com código PHP: você utiliza a linguagem que precisar para apresentação do conteúdo (HTML, CSS, XML, JavaScript ou qualquer outra que desejar) e pode embutir código Python no meio. A grande sacada - que trás muita simplicidade e flexibilidade ao desenvolvedor - é exatamente o fato de podemos embutir código Python. Com isso, ganhamos inúmeras vantagens:
- Você não precisa aprender a utilizar uma linguagem de templates nova: é Python - mesma linguagem em que você programa seus models e controllers!
- Como o código da view pode ser transformado em um módulo Python, a execução da view fica muito mais rápida, pois o web2py a traduz para código Python puro e então o compila para bytecode;
- Você não fica limitado a uma linguagem restrita (como são as linguagens criadas para a camada de apresentação) - você pode utilizar todo o poder que Python lhe proporciona sempre!
- Você pode criar qualquer formato de saída para sua camada de apresentação, o que significa que não necessariamente a saída da sua view precisa ser escrita em alguma linguagem de marcação (HTML, XML etc.). Você pode, por exemplo, ter uma view que gera um arquivo JPEG, um texto em RTF, um documento em PDF, um arquivo em CSV e por aí vai;
- A camada de apresentação está desacoplada das outras camadas, o que significa que uma única view pode servir a vários controllers ou um único controller pode ter como apresentação várias views diferentes em ocasiões diferentes.
Eu poderia citar vários outros exemplos (inclusive da ótima integração da camada de apresentação com as outras camadas do framework), mas as outras dicas ficarão diluídas nos próximos artigos. Porém, não poderia deixar esse artigo sem código. Como todo bom programador, vamos ao que interessa:
Exemplo 1 - View gerando HTML
Digamos que possuímos um sistema de inscrição em eventos e precisamos listar uma tabela com o nome do participante inscrito e assinalar se ele pagou ou não a inscrição. Dessa forma, possuímos um model (por exemplo, models/db.py) parecido com:
db.define_table('participante',
Field('nome', 'string', length=250),
# inclua outros campos aqui
Field('pagou', 'boolean'),
)
Então precisamos de um controller que seleciona os nomes dos inscritos e o estado do pagamento. Vamos chamar esse controller de controllers/usuarios.py:
def tabela_de_pagamentos():
inscritos = db().select(db.participante.nome, db.participante.pagou,
orderby=db.participante.nome)
return {'nome_e_pagamento': inscritos}
Com isso, nossa view será executada em um ambiente onde a variável nome_e_pagamento existe e seu conteúdo é o que foi retornado pelo controller acima. Vamos então criar uma view que gera HTML para o controller acima. Coloque no arquivo views/usuarios/tabela_de_pagamentos.html:
{{if len(nome_e_pagamento) == 0:}}
Não temos usuários cadastrados! :-(
{{else:}}
<table>
<tr>
<td> Nome </td>
<td> Pagou? </td>
</tr>
{{
for usuario in nome_e_pagamento:
if usuario.pagou:
pagou = 'Sim'
else:
pagou = 'Não'
pass
}}
<tr>
<td> {{=usuario.nome}} </td>
<td> {{=pagou}} </td>
</tr>
{{pass
pass}}
Tudo o que está entre {{...}} será executado como código Python. Além disso, o web2py inclui algumas novas palavras-chave para ajudar no processo de criação de views, são elas:
- {{=expressão_Python}}: executa expressão_Python e imprime o resultado no local;
- {{extend 'arquivo.html'}}: utiliza a view arquivo.html como base para essa view;
- {{include}}: indica onde outras views que utilizam essa como base serão adicionadas.
Pode parecer estranho acima o uso da keyword pass. Elas estão lá por conta de uma definição no sistema de apresentação do web2py: por conta de espaços na camada de apresentação fazerem diferença, seria complicado em todos os casos o programador manter a endentação correta do código.
Para resolver esse problema o web2py então gera um novo código baseado em nossa view, ignorando a endentação que utilizamos - ele auto-endenta o código quando encontra if, for etc. Para voltar um nível, como a endentação na view é ignorada, precisamos utilizar a palavra reservada do Python pass. Note que essa palavra reservada faz parte da linguagem e sua função é apenas "passar" (não executa comando algum) - nesse caso ela serve como um sinal para o web2py voltar um nível na endentação.
Note que como a endentação é feita automaticamente, eu não precisaria ter endentado o código entre {{...}}. Porém nesse caso a endentação não atrapalha o código de retorno da minha view e por motivos de organização deixei o código endentado.
Para o exemplo acima, se acessarmos a URL http://localhost:8000/welcome/usuarios/tabela_de_pagamentos (ou http://localhost:8000/welcome/usuarios/tabela_de_pagamentos.html) teríamos como retorno a view acima processada, como nos dois exemplos abaixo, sem e com dados inseridos na tabela:
Nota: utilizei/modifiquei a aplicação welcome (que já vem com o web2py) para fazer esses exemplos.
Exemplo 2 - View gerando CSV
Para os mesmos model e controller acima poderíamos ter uma view que gera um arquivo CSV com os dados, em vez de HTML. Vamos então criar o arquivo views/usuarios/tabela_de_pagamentos.csv:
{{
import cStringIO
csv = cStringIO.StringIO()
nome_e_pagamento.export_to_csv_file(csv)
response.write(csv.getvalue())
csv.close()
}}
Não vou entrar em detalhes do código acima, mas para quem estranhou a presença do objeto response fica a explicação: o web2py, para aumentar a produtividade do desenvolvedor, leva a sério o conceito Don't Repeat Yourself e, por isso, ele mesmo importa automaticamente os objetos de sua API que precisamos utilizar (nesse caso, o objeto response).
Feito o código acima, ao entrarmos em http://localhost:8000/welcome/usuarios/tabela_de_pagamentos.csv será feito o download de um arquivo CSV. Abrindo, teremos:
Como disse acima, poderíamos utilizar outras extensões nas views e gerar quaisquer tipos de arquivos que quisermos com código Python. Em uma aplicação que desenvolvi há alguns meses precisei criar views que gerassem PDF (para relatórios sob demanda) e tudo funcionou perfeitamente.
Espero que os exemplos acima tenham explicitado o poder e flexibilidade que esse sistema de apresentação possui. Dúvidas? Entre na lista brasileira de usuários web2py e perguntem-me lá!