Inserindo rotas no web2py

Posted by Gilson Filho on Qua 04 maio 2011

Olá pessoal,

Normalmente quando você programa alguma funcionalidade, o endereço que a compõem não é tão intuitiva quanto você queria, isso acontece muitas das vezes. Por exemplo, vamos ver a URL abaixo:

http://www.app.com/default/index

Apesar de você acessar com www.app.com, fica com endereço feio e sem nexo. Porque default? Porque index? Para quem desenvolveu sabe, mas e para o usuário? O web2py como o Django, tem a opção de reescrever esses endereços da sua aplicação que também é chamado de rotas.

Inicialmente apanhei muito a mecher com as rotas, mas como sou brasileiro e não desisto nunca, acabei conseguindo fazer algumas coisas :P. Antes de mais nada, você precisa saber o básico de Expressões Regulares, e para mais informações você pode acessar aqui.

Caso queira aprofundar mais sobre Expressões Regulares (sendo que todo desenvolvedor tem que saber), tem esse livro que recomendo:

Expressões Regulares - Uma Abordagem Divertida

Já sabendo usar o básico de ER, vamos iniciar o post.

Arquivo routes.py

O web2py usa o arquivo chamado routes.py que recebe toda as configurações das rotas dos aplicativos que rodam no web2py. Nele você pode especificar endereços de uma ou mais aplicações. Abaixo mostra o conteúdo do arquivo vindo do framework, com exemplos e comentários:

Vou explicar cada parte do arquivo:

  1. No início do arquivo temos três configurações a fazer:

    1. default_application: Especifica a aplicação padrão que vai ser executada;

    2. default_controller: Especifica o controller da aplicação acima que vai ser executada por padrão;

    3. default_function: Especifica a action do controller padrão a ser executada.

Elas são importantes para deixar claro o que deve ser executado quando invocar a aplicação. No caso do routes_app, não vou explicar porque vou mostrar o essencial desse arquivo. Mas o foco dele é as opções routes_in e routes_out.

Alterando uma URL simples

Personalizando sua URL com routes_in

A opção routes_in é uma tupla de tuplas, que armazena dois parâmetros: o endereço personalizado, e a URL original do projeto. Para quem programa em Django, vai perceber que é idêntico o arquivo urls.py (com a diferença que no segundo parâmetro você insere o endereço original, invés da view da aplicação django):

routes_in = (
        # Login e Registro
        (r'/login',r'/app/user/login'),
        ...
)

Como você pode ver temos dois parâmetros. No primeiro é a URL personalizada, a que vai ser acessada via browser como também visualizada. Com isso ao invés de ser http://www.app.com/user/login, vai passar a ser http://www.app.com/login.

Adaptando a nova URL no seu projeto com routes_out

No web2py, quando queremos especificar um endereço, tanto na camada de controle (para redirecionamentos), como para a camada de visualização, usamos a função URL(). Usando o routes_in não é o suficiente, porque quando usar a função URL(), ele vai requisitar e exibir a URL original. Então, o routes_out serve para "converter" os endereços originais usados na URL() para os personalizados. Ficou confuso? Olhe o exemplo abaixo:

{{extend 'layout.html'}}
(...)
<a href="{{=URL('user','login')}}">Clique Aqui</a>

Vendo o código acima, estamos usando o URL() para refenciar ao login usado no exemplo anterior. Se não configurarmos no routes_out também ele exibirá o endereço original. Tanto que isso é verdade, que quando você coloca o mouse em cima do link, na barra de status do seu navegador vai provar isso. Mas para mudar isso como faço? Configurando a URL no routes_out. É o contrário feito no routes_in:

routes_out = (
        # Login e Registro
        (r'/app/user/login',r'/login'),
        ...
)

Viu? Bem simples. Com isso, ao executar a aplicação, o web2py vai reconhecer que a URL foi sobrescrita no arquivo routes.py e vai tratar isso automaticamente.

Inserindo argumentos nas URLs em routes.py

Essa foi a situação mais chata que passei até então com o routes.py. Como vou personalizar endereços que enviam dados usando argumentos na aplicação? Eu pesquisei, e estava dificil de encontrar, tanto que nem encontrei :P, mas por persistência descobri como fazer isso. E o pior que não tem muito mistério, você vai entender o porque. Vamos pensar que queremos enviar um ID para consultar os dados do usuario. Com isso temos o controlador user com a action profile. O endereço original está assim:

http://www.app.com/user/profile/1

Só que você quer deixar dessa forma:

http://www.app.com/profile/1

Como faço isso? No web2py, você pode criar váriaveis que representam os argumentos que ficam no Request. Aqui a variável é o $args, que está sendo usada nesse post. Você pode colocar qualquer nome nessa variável como $id, $argumento, enfim, o que sua imaginação conseguir. Vamos ver como isso fica no routes.py:

#Routes In
routes_in = (
        # Login e Registro
        (r'/login',r'/app/user/login'),
        (r'/profile/$args',r'/app/user/profile/$args'),
        ...
)

# Routes Out
routes_out = (
        # Login e Registro
        (r'/app/user/login',r'/login'),
        (r'/app/user/profile/$args',r'/profile/$args'),
        ...
)

Declarado o $args no arquivo. Vamos ver como faço para capturar esses argumentos:

# coding: utf-8

def index():
    return locals()

def profile():
    if len(request.args):
        id = int(request.args(0))
    (...)
    user = db(...)
    return dict(user=user)

Não tem muita diferença quando usa as rotas. Você verifica se possui algum argumento usando a condicional na linha 7. Caso tenha algum argumento, capture o primeiro da lista, ou seja, o request.args(0).

Usando mais de um argumento no routes.py

No caso de mais de um argumento, você cria uma outra variável para isso. Você não usa um array ou coisa semelhante, você gera uma outra variável que represente o índice de request.args:

#Routes In
routes_in = (
        # Login e Registro
        (r'/login',r'/app/user/login'),
        (r'/profile/$args1/$args2',r'/app/user/profile/$args1/$args2'),
        ...
)

Com isso no controlador, você vai capturar esses dados da seguinte forma: no $args1 ele vai ficar no índice 0 do request.args, e o $args2 _vai ficar no índice 1 do _request.args, e assim por diante:

# coding: utf-8

def index():
    return locals()

def profile():
    if len(request.args):
        id = int(request.args(0))
        outro_id int(request.args(1))
    (...)
    user = db(...)
    return dict(user=user,outro_id=outro_id)

E então quando acessar o sistema, podemos usar como no endereço abaixo:

http://www.app.com/profile/1/2

Viu? É tão simples e tão óbvio!! :P. Por enquanto é só o básico, mas quando for pegando mais macetes como esses eu vou postando aqui.

Abaixo tem uma vídeo aula explicando o uso das rotas no web2py:

Criando URLs amigáveis em suas aplicações web2py from Gilson Filho on Vimeo.

Então é só isso. Até mais :)



Comments !