Francisco Souza

Open source, Python, Django, Java, agile e outras coisas mais

Voando Com O Web2py No Google App Engine

web2pyChegamos à segunda parte da série de posts sobre o uso de frameworks Python no Google App Engine. O framework da vez é o web2py, um leve e poderoso framework web fullstack. Assim como o Django, um dos principais recursos do web2py é uma poderosa camada de abstração dos dados (DAL - data abstraction layer), mas diferente do Django, a camada de abstração de dados do web2py foi projetada para dar suporte a bancos de dados não-relacionais, e conta com suporte nativo ao BigTable.

Antes de tudo, devemos configurar nosso ambiente. Para isto, é necessário acessar o site oficial do web2py e baixar o arquivo web2py_src.zip na seção de downloads. Após baixar o pacote zip, basta extraí-lo. Será criado um diretório chamado web2py, onde nosso projeto estará localizado. A estrutura de projeto padrão fornecida pelo web2py já vem preparada para o Google App Engine, isto significa que há um arquivo app.yaml pronto para ser personalizado:

[cc lang=”yaml”]application: gaeseries version: 2 api_version: 1 runtime: python

handlers:

skip_files: | ^(./)?( (app.yaml)| (app.yml)| (index.yaml)| (index.yml)| (#.#)| (.~)| (..py[co])| (./RCS/.)| (..)| ((admin|examples|welcome).tar)| (applications/(admin|examples)/.)| (applications/.?/databases/.) | (applications/.?/errors/.)| (applications/.?/cache/.)| (applications/.?/sessions/.)| )$[/cc]

As únicas mudanças estão localizadas nas duas primeiras linhas: o nome da aplicação e a sua versão, como esta é a segunda parte da série de posts, então eu configurei a aplicação gaeseries na versão 2.

Dentro da estrutura gerada pelo web2py, existe um diretório chamado applications, é neste diretório que ficam as aplicações do web2py. O web2py fornece por padrão uma aplicação chamada welcome que serve como esqueleto para a criação de novas aplicações. Para criar a aplicação blog, basta copiar o diretório welcome com um novo nome: blog. Este é o procedimento adotado para criar qualquer aplicação. Agora que temos a aplicação criada, vamos seguir com os mesmos passos do post sobre Django: serão duas actions dentro de um controller, uma para listar todos os posts registrados no blog e outra para escrever um post.

A primeira coisa a fazer é definir o modelo, nossa tabela no banco de dados. Dentro do diretório da nossa aplicação (blog), existe um subdiretório chamado models contendo um módulo Python chamado db.py. É neste arquivo que definimos nossos modelos. Note que o web2py fornece diversas configurações por padrão, como a integração com o BigTable e o sistema de autenticação (que usaremos mais adiante). Vamos apenas adicionar ao final do arquivo nosso modelo post, com o seguinte código:

[cc lang=”python”]current_user_id = (auth.user and auth.user.id) or 0

db.define_table(‘posts’, db.Field(‘title’),

            db.Field('content', 'text'),
            db.Field('author', db.auth_user, default=current_user_id, writable=False),
            db.Field('date', 'datetime', default=request.now, writable=False)
           )

db.posts.title.requires = IS_NOT_EMPTY() db.posts.content.requires = IS_NOT_EMPTY()[/cc]

O código pode parecer estranho, mas é bastante simples: foi definida uma tabela no banco de dados (define_table) chamada posts, com quatro campos: title (uma string) , content (outra string =P), author (uma referência para a tabela auth_user, fornecida pela aplicação de autenticação nativa do web2py) e date (do tipo data, com preenchimento automático com a data e hora corrente). Nas duas últimas linhas, foram definidas as validações para os campos title e content.

Com o modelo configurado, podemos definir o controller e suas actions. No web2py, os controllers são módulos Python que ficam dentro do diretório controllers (na estrutura da aplicação). Dentro de cada módulo Python, definimos funções que representam as actions do controller. O web2py conta com a seguinte convenção para URLs: /<aplicação>/<controller>/<action>. Assim, vamos criar um controller chamado posts que será acessado na URL /blog/posts. Nesta URL, exibiremos a listagem de posts. Para isto, definimos a action index dentro do controller posts.py:

[cc lang=”python”]def index():

posts = db().select(db.posts.ALL)
return response.render('posts/index.html', locals())[/cc]

O código é pequeno e simples, um padrão do web2py :) Na primeira linha, nós listamos todos os posts presentes no banco de dados e na segunda linha nós encaminhamos estes posts para a renderização da view posts/index.html. No web2py, as views ficam localizadas dentro do diretório views da aplicação. Assim, dentro do diretório blog/views devemos criar a nossa view, com o seguinte código: http://gist.github.com/509116.

Podemos conferir o resultado executando o servidor de desenvolvimento do Google App Engine localmente com um simples comando (tenho a SDK do Google App Engine dentro de /usr/local/google_appengine):

$ /usr/local/google_appengine/dev_appserver.py .

O comando deve ser executado dentro da raiz do projeto. Assim, quando acessarmos no browser a URL http://localhost:8080/blog/posts veremos a listagem de posts. Na verdade, não, pois ainda não há nenhum post cadastrado ;P Bom, vamos então criar a action protegida por login para salvar um post no banco de dados. Eis o código da action:

[cc lang=”python”]@auth.requires_login() def new():

form = SQLFORM(db.posts, fields=['title','content'])
if form.accepts(request.vars, session):
    response.flash = 'Post saved.'
    redirect(URL('blog', 'posts', 'index'))
return response.render('posts/new.html', dict(form=form))[/cc]

Note que action foi decorada com o decorator auth.requires_login(), que indica que para acessar esta action o usuário deve estar autenticado no sistema. A aplicação de autenticação do web2py provê uma action de login, assim como action para registro do usuário, não é necessário se preocupar com isso. Eis aqui o código da view posts/new.html: http://gist.github.com/509125.

Totalmente simplório, o web2py sabe se virar muito bem sozinho :)

Finalmente nossa aplicação está pronta para ir para produção nos servidores do Google App Engine, então podemos executar o deploy de maneira mágica:

$ /usr/local/google_appengine/appcfg.py update .

E pronto! A aplicação está online e disponível no endereço http://2.latest.gaeseries.appspot.com. Você pode se logar utilizando o usuário demo@demo.com com a senha demo.

O código da aplicação está disponível no Gitbub: http://github.com/fsouza/gaeseries/tree/web2py.