Passo-a-Passo web2py, 2º passo

Vimos anteriormente, no 1º passo, como executamos o web2py e como criamos nossas aplicações da maneira mais simples.  Agora, podemos colocar esse conhecimento em prática e começar a desenvolver nossa aplicação da locadora. Vamos lá!

Segue o índice para que você acompanhe também os outros passos:

Organização do Ambiente de Desenvolvimento

Como vimos, o web2py já vem pronto para ser executado e podemos começar o desenvolvimento de algo novo em pouquíssimo tempo. Ou seja, o framework traz consigo todo um ambiente preparado para o desenvolvimento, sem que você tenha que configurar nada para começar a programar.

Também vimos que o web2py traz consigo uma interface administrativa que inclui editores de código, o que permite que alteremos nossa aplicação e seu código direto no browser.

Porém, para entendermos como o ambiente do web2py foi organizado e desenvolvermos nossa aplicação, neste passo-a-passo não iremos utilizar a IDE embutida do web2py e iremos explorar a estruturação do framework. Então, para começarmos, dê uma olhada na pasta que você descompactou do web2py:

Diretório descompactado do web2py

Diretório descompactado do web2py

A maior parte do conteúdo desta pasta não fará grande diferença para você enquanto desenvolve, mas existem alguns que merecem um certo destaque:

  • O diretório applications  contém todas as aplicações que você criou no web2py. Cada aplicação é uma pasta que contém diversos outros conteúdos que analizaremos também adiante.
  • O diretório examples contém arquivos de exemplo que você pode usar como modelo para várias funcionalidades do web2py. Por exemplo: configurações de rota, configurações de logging, configurações do appengine, entre outros.
  • O diretório gluon contém os módulos e arquivos que literalmente constroem o framework.
  • O arquivo web2py.py, que é o arquivo que inicia a execução do framework.

Como eu falei, o web2py vem todo preparado para você já começar a desenvolver suas aplicações, então você não vai precisar alterar nenhum desses arquivos para partirmos para a nossa aplicação. Esse tour foi apenas para você conhecer um pouco mais da organização do framework.

Agora, acesse a pasta applications e, dentro dela, acesse a pasta welcome.

Diretório da aplicação Welcome

Diretório da aplicação Welcome

Basicamente, aí estão as pastas que nós já vimos a partir da interface administrativa. Ou seja, ao editar qualquer arquivo por um editor de texto no seu computador, você estará seguindo o mesmo processo de editá-lo via interface administrativa que vimos antes.

Temos também algumas pastas que não conseguimos ver na interface administrativa. Essas pastas geralmente contém logs ou informações que o web2py armazena durante a execução da nossa aplicação e são de controle do framework. A pasta databases, por exemplo, contém logs da criação de tabelas no banco de dados e, no caso da configuração padrão do web2py, o banco de dados .sqlite da nossa aplicação.

A partir de agora, você pode escolher seu editor favorito e vamos começar a programar!

Abrindo nossa locadora

Primeiro, devemos criar a nossa nova aplicação. Acesse a interface administrativa e crie uma nova aplicação chamada locadora.

Seguindo o modelo MVC, devemos começar pelos models, assim teremos conteúdo para trabalhar nos controllers e para exibir ao usuário nas views. Agora, vamos pensar: o que uma locadora deve ter?

Bom, uma locadora é um lugar que as pessoas vão para alugar filmes. Então precisamos ter filmes, um estoque e pessoas para alugar esses filmes. Essas são nossas tabelas do banco de dados. Vamos começar a construí-las:

Abra o arquivo db.py que fica dentro da pasta models da sua aplicação.

Arquivo db.py da pasta models

Arquivo db.py da pasta models

Agora vamos analizar esse arquivo.

from gluon.contrib.appconfig import AppConfig
myconf = AppConfig(reload=True)

Aqui estamos associando as configurações da aplicação a uma variável myconf.

if not request.env.web2py_runtime_gae:
    db = DAL(myconf.take('db.uri'), pool_size=myconf.take('db.pool_size', cast=int), check_reserved=['all'])
else:
    db = DAL('google:datastore+ndb')
    session.connect(request, response, db=db)

Assim realizamos nossa conexão a um banco de dados que está especificado nessas configurações.

Configurações

Mas o que são essas tais configurações? O arquivo de configurações do web2py fica na pasta private da sua aplicação e vem com o nome appconfig.ini. Você pode abri-lo e verá que ele vem com valores padrões, ou seja, com configurações que o web2py traz por padrão.

Este arquivo pode ser personalizado da maneira que você desejar. Para isso, basta entender que cada nome entre colchetes (por exemplo [db], [smtp] ou [forms]) terá seus valores mapeados pela classe AppConfig, assim tornando mais simples acessar as informações de configuração.

Observe:

; db configuration
[db]
uri       = sqlite://storage.sqlite
migrate   = 1
pool_size = 1

Assim, como chamamos  nosso arquivo de configuração de myconf, ao fazer myconf.take(‘db.uri’) estamos na verdade pegando o valor sqlite://storage.sqlite. Caso você quisesse alterar a URI do seu banco de dados, por exemplo, você iria alterar esse valor.

De volta ao db.py

Continuando a analizar o arquivo db.py, agora que entendemos como ele trouxe as configurações, temos:

from gluon.tools import Auth

auth = Auth(db)
auth.define_tables(username=False, signature=False)

Aqui omiti algumas linhas de menor importância.

O que temos é a importação da classe Auth. Essa classe é o que permite ao web2py fazer todo o controle de autenticação de usuários. Basicamente, o Auth irá criar todas as tabelas de usuário no banco de dados que passamos para ele (no nosso caso, aquele associado à variável db) sozinho a partir do comando auth.define_tables() que usamos.

Além disso, ele irá fazer o controle de permissões, como veremos adiante, para saber se aquele usuário tem permissão para acessar determinada página, qual a categoria do usuário, se ele está realmente logado na página, etc.

Para fazer todo esse controle, o web2py cria, além de uma tabela de usuários, uma tabela de grupos, uma de permissões, etc. Mas a única que irá nos interessar no momento é a tabela de usuários. Os campos da tabela que nos interessam (e não são preenchidos automaticamente pelo web2py) são:

  • First name: O primeiro nome do usuário.
  • Last name: O sobrenome do usuário.
  • E-mail: O e-mail do usuário.
  • Password: A senha do usuário, que é criptografada automaticamente e armazenada dessa forma.

Outros campos que por ventura você veja nessa tabela, são para o web2py fazer controle de algumas das suas funcionalidades.

Disso podemos riscar um item da nossa lista: nós já temos pessoas! Temos toda a tabela de usuários criada, agora só precisamos de filmes para montar nosso estoque.

Para criarmos a tabela de filmes, vamos pensar novamente: o que filmes tem? Bom, filmes tem um título, um ano de lançamento, uma duração, um ou mais gêneros, um diretor e uma capa/cartaz. Claro que filmes tem muito mais conteúdo que isso, mas geralmentes esses são os principais detalhes que identificam um filme.

Usando essa lógica, além de esses serem os detalhes de um filme, eles serão os campos da nossa tabela.

Ao final do arquivo db.py, escreva:

Filmes = db.define_table('filmes',
Field('titulo', 'string', label='Título'),
Field('lancamento', 'integer', label='Lançamento'),
Field('duracao', 'integer', label='Duração'),
Field('generos', 'list:string', label='Gêneros'),
Field('diretor', 'string', label='Diretor'),
Field('capa', 'upload', label='Capa/Cartaz')
)

Vamos entender:

db.define_table(nome, campos...)

é o método que usamos para criar novas tabelas. db é uma variável que definimos no início do arquivo db.py e ela é a nossa conexão com o banco de dados. Assim, ao chamar

db.define_table(nome, campos...)

estamos falando para criar uma tabela nome com os campos passados. No nosso caso, criamos uma tabela chamada filmes com os campos que mencionamos anteriormente.

Além disso, associamos essa tabela à variável Filmes. Ou seja, sempre que chamarmos Filmes, estamos apenas chamando essa tabela que acabamos de criar.

Cada campo da tabela é criado como um Field(). Um Field pode ter várias opções (você pode ver todas clicando aqui), mas as mais importantes para nós no momento são:

  • Nome do campo é o nome que esse campo terá na sua tabela. Os nomes devem ser definidos quase com as mesmas regras das variáveis, sem caracteres especiais, etc.
  • Tipo do campo, que é quase a mesma tipagem das variáveis de Python. Podem ser strings, integers, etc (veja todos os tipos clicando aqui). Alguns tipos são especiais, como o tipo upload, que guarda um arquivo, e o tipo list:<outro_tipo>, que armazena uma lista de valores daquele tipo especificado.
  • Label do campo, que é o nome visível do campo. Quando aprendermos a gerar formulários a partir dos campos da tabela, você verá que o título de cada campo do formulário baseia-se no nome do campo. No nosso caso, alguns campos como o descricao, tem nomes sem acento e sem cedilha, o que prejudica a leitura desse nome. Por isso, passamos na label aquele nome que queremos que seja exibido no lugar do nome real do campo.

Ok, podemos riscar da lista também a tabela de filmes, ela está pronta! Próximo passo: criar nossa tabela de controle de estoque. O que nós precisamos em um controle de estoque? A primeira coisa, com certeza, são produtos; além de produtos, precisamos controlar o preço deles; por fim, a quantidade.

Então, ficaria mais ou menos assim:

ItemsEstoque = db.define_table('items_estoque',
    Field('filme', 'reference filmes', label='Filme'),
    Field('quantidade', 'integer', label='Quantidade'),
    Field('preco', 'float', label='Preço')
    )

Temos uma tabela fazendo um controle dos produtos que temos em estoque. Vamos apenas entender um novo tipo de campo: reference filmes.

Um campo do tipo reference é usado sempre que queremos relacionar uma tabela com outra. Assim, usamos reference <nome_da_tabela>. Nesse caso, estamos relacionando nosso campo filme com a tabela filmes,ou seja, o campo filme tem que ser um registro presente na tabela filmes.

Obs: note que, para referenciar, utilizamos o nome real da tabela, e não o nome da variável associada a ela.

Terminamos com as tabelas, certo? Bem, ainda não… Quando criamos tabelas para armazenar valores, lembramos sempre dos valores mais palpáveis, mas costumamos esquecer que temos que armazenar informações do que acontece no processo.

No nosso caso, pensamos em tudo o que uma locadora precisa ter para ser uma locadora, mas esquecemos que precisamos registrar sempre que um cliente locar um filme, ou vamos acabar perdendo o controle sobre os filmes locados!

Por isso, vamos criar uma tabela para armazenar essas informações:

Locacao = db.define_table('locacoes',
    Field('filmes', 'list:reference filmes', label='Filme'),
    Field('cliente', 'reference auth_user', label='Cliente'),
    Field('data_locacao', 'datetime', label='Data de Locação'),
    Field('data_devolucao', 'datetime', label='Data de Devolução'),
    Field('multa', 'float', label='Multa')
    )

Os nossos novos tipos de campos são:

  • list:reference <nome_tabela>, que é o mesmo que armazenar uma lista normal, mas agora essa lista será preenchida por registros da tabela filmes.
  • datetime que é um campo que armazena data e hora, como o nome bem diz.

Obs: auth_user é o nome da tabela de usuários que o web2py cria.

Agora podemos armazenar as informações de locação de filmes toda vez que um cliente levar alguns filmes para casa.

Database Abstraction Layer (DAL)

Agora que temos uma conexão com o banco de dados criada (variável db) e todas as nossas tabelas prontas, fica mais fácil entender o que é a DAL do web2py, ou a Camada de Abstração de Banco de Dados.

A DAL nada mais é que uma API que mapeia objetos Python em objetos de banco de dados como queries, tabelas e registros. Isso significa que coisas de bancos de dados, como tabelas, são trasnformadas em objetos Python para que você consiga interagir com elas.

A DAL gera SQL dinamicamente, em tempo real, usando um dialeto específico para o back end do banco de dados utilizado para que você não tenha que escrever SQL ou sequer aprender diferentes dialetos SQL. Dessa forma, a aplicação também torna-se compatível com vários e diferentes tipos de bancos de dados.

O web2py dá suporte aos bancos de dados mais conhecidos, como SQLite, PostgreSQL, MySQL, Oracle e MongoDB entre outros.

Basicamente, toda aquela criação de tabelas deveria ter sido feita com SQL, certo? Mas, usando a DAL, criamos tudo usando Python e, por trás disso, a DAL fez a conversão para SQL e todas as interações necessárias com o banco de dados.

Conclusão

Neste 2º passo vimos como o web2py vem organizado para utilização, quais os elementos padrões que ele traz e como isso facilita tudo para que possamos já começar a programar algo novo assim que o download do framework foi feito.

Entendemos também como funcionam as configurações que o framework traz, principalmente aquelas relacionadas ao banco de dados, e demos o primeiro mergulho dentro dos models nos conectando ao banco de dados e criando tabelas.

A aplicação está disponível nesse repositório: https://github.com/juliarizza/locadora. Cada passo apresentado será um branch, então tudo o que fizemos neste passo estará no branch passo2.

Espero você para darmos o próximo passo!

19 comentários sobre “Passo-a-Passo web2py, 2º passo

  1. Denival Jeter Guimarães disse:

    Boa tarde Júlia. Estou desenvolvendo um sisteminha utilizando o Web2py, para rodar localmente, na maquina de alguns clientes, pois estes não teriam acesso a nossa rede interna. A aplicação seria um “pedaço” do que temos aqui, e os clientes precisam carregar alguns dados que vamos utlizar para fazer alguns cálculos mensais.
    Acontece que na aplicação web2py que vou usar aqui e que vai exportar os dados para a aplicação dos clientes vou precisar acessar duas bases de dados, uma Postgres (nosso servidor, que é a base quente) e outra base sqlite que será acoplada na aplicação dos clientes e encaminhada para eles via email.
    Como faço para utlizar duas bases simultaneamente no web2py (postgres e sqlite)?
    Obrigado e o tutorial está me ajudando muito.

    Curtir

    • Júlia Rizza disse:

      Oi Denival,

      Você pode fazer várias conexões ao banco de dados. Da mesma forma como associamos a nossa conexão primária à variável db:

      db = DAL(‘sqlite://…’)

      Podemos associar uma segunda conexão à outra variável:

      sec_db = DAL(‘postgres://…’)

      Curtir

      • Denival Jeter Guimarães disse:

        Júlia, inclui a segunda base na minha aplicação.
        Nos testes deu tudo certo.
        Porém a base de dados quente trabalha com “schemas”.
        Como acessar os “schemas” via web2py?

        Curtir

      • Denival Jeter Guimarães disse:

        Bom dia Julia,
        Foi isso mesmo, usei com o comando:
        db.executesql(sql)
        E escrevi as instruções sql conforme o padrâo, segue exemplo:
        sql = “select from . order by ;”
        rows = db2.executesql(sql)
        e usei a variável rows em um SQLFORM.factory

        Curtir

  2. Jorge Reis disse:

    Julia, boa tarde
    estou seguinte os passos, porem instalei agora set/2016 e a versao do web2py é superior a do curso, pode ser feito nesta versao mais nova? ou deve ser feito na versao que voce usou, falo isso porque ao final do segundo passo, da erro ao tentar visualizar a aplicação.

    Curtir

Deixe um comentário

Este site utiliza o Akismet para reduzir spam. Saiba como seus dados em comentários são processados.