Compartilhe com seus amigos!

26 minutos de leitura

Caso você seja um desenvolvedor web ou python e esteja desenvolvendo um app para a internet utilizando o Python, tem grandes chances de você estar utilizando um framework. Um framework “é uma biblioteca de códigos que torna a vida do desenvolvedor mais fácil, quando se fala de aplicativos, escaláveis e fáceis de manter”, fornecendo códigos reutilizáveis ou extensões para operações comuns. Existem diversos frameworks para o Python, incluindo Flask, Tornado, Pyramid e Django, mas nesse artigo abordaremos o Flask.

 

Nesse artigo iremos guiar vocês no processo de construir um API sendo esse processo um simples To-do list (lista de afazeres). O Flask Python é bem direto ao ponto:

 

To-do list (lista de afazeres).

 

  • Fazer com que novos visitantes ao site sejam capazes de registrarem novas contas.

 

  • Fazer com que usuários registrados possam logar, deslogar, ver informações sobre seus perfis e editar suas informações.

 

  • Fazer com que os usuários registrados possam criar novos itens de tarefas, visualizar suas tarefas existentes e editar também.

 

Tudo isso é para formar um conjunto compacto de endpoints de APIs que todo desenvolvedor backend deve implementar, junto dos métodos de HTTPS permitidos:

 

GET /

POST /accounts

POST /accounts/login

GET /accounts/logout

GET, PUT, DELETE /accounts/

GET, POST /accounts//tasks

GET, PUT, DELETE /accounts//tasks/

 

Cada framework possui o seu jeito único de colocar seus routes, models, views, interações com o banco de dados e configuração geral do aplicativo

 

Se quiser pular para uma parte em específico utilize nosso menu de conteúdos:

 

  1. Inicialização e configuração do Flask Python
  2. Conectando o banco de dados com o Flask Python
  3. Definindo objetos em Flask Python
  4. Relacionamento dos models
  5. Inicializando o banco de dados
  6. Views e configuração de URL
  7. Solicitações Flask e DB
  8. Conclusão Flask Python

 

 

Inicialização e configuração do Flask Python

 

 

Igual às bibliotecas de python bastante utilizadas, o pacote Flask é instalável através do Python Package Index (PPI). Primeiro crie um diretório para trabalho (tipo flask_todo seria um bom nome) aí então instale o pacote flask. Também instale o flask-sqlalchemy para que o seu flask tenha um jeito simples de se comunicar com um banco de dados SQL.

 

Nós iremos trabalhar utilizando o ambiente virtual do Python 3. Para fazer isso, digite o seguinte na linha de comando:

 

 

Caso queira transformar isso em um repositório Git, aqui é um bom lugar para rodar git init. Isso será a raiz do projeto, e se você quiser exportar o código base para uma máquina diferente, será bastante útil ter todos os arquivos de setup aqui.

 

Uma boa forma de começar é transformar o código base em distribuição python instalável. Na raiz desse projeto, crie um setup.py e um diretório chamado todo para conter o código fonte.

 

o setup.py deve parecer dessa forma:

 

Dessa forma, quando você quiser instalar ou lançar seu projeto, você terá todos os pacotes necessários na lista requires. Você também terá tudo que precisa para configurar e instalar o pacote em site-packages. Caso queira mais informações de como escrever uma distribuição python instalável, visite esse site the docs on setup.py.

 

Dentro do diretório chamado todo que contém o código fonte, crie um arquivo app.py e um arquivo em branco __init__.py. O arquivo __init__.py permite que você importe do todo como se fosse um pacote instalado. O arquivo app.py será a raiz do aplicativo. É para aqui que todas as vantagens do aplicativo Flask irão estar, e você irá criar uma variável de ambiente que aponta para esse arquivo. Se você estiver utilizando pipenv, você consegue localizar seu ambiente virtual com pipenv –venv e configurar essa variável de ambiente no script activate do seu ambiente.

 

 

Quando você instalou o Flask, você também instalou o script de linha de comando flask. Se você digitar flask run solicitará que o pacote Flask do ambiente virtual rode um server HTTP utilizando o objeto app em qualquer script que a variável de ambiente FLASK_APP esteja apontando. O script acima também inclui uma variável de ambiente chamada DEBUG que nós utilizaremos depois.

 

Vamos falar sobre esse objeto chamado app.

 

No todo/app.py, você irá criar um objeto app, no qual é uma instância do objeto Flask. Ele irá agir como o objeto de configuração central para o aplicativo inteiro. É utilizado para configurar pedaços do aplicativo que são necessárias para estender a funcionalidade, por exemplo, uma conexão com um banco de dados e ajuda com autenticação.

 

É utilizado regularmente para configurar as routes (rotas) que se tornarão os pontos de interação do aplicativo. Para explicar o que isso significa, vamos dar uma olhada no código que isso corresponde.

 

 

Esse é o aplicativo Flask Python mais básico e completo. app é uma instância do Flask, obtendo o __name__ arquivo de script. Isso permite com que o Python saiba como importar de arquivos relativos a esse. O decorador app_route decora a primeira função view; ele consegue especificar uma das rotas utilizadas para acessar o aplicativo. (Falaremos a respeito disso daqui a pouco).

 

Qualquer view que você especifique deve ser decorado por app_route para ser uma parte funcional do aplicativo. Você pode ter quantas funções quiser espalhadas pelo aplicativo, mas para essa funcionalidade ser acessível para qualquer coisa externa ao aplicativo, você deve decorar essa função e especificar a rota para torná-la uma view.

 

No exemplo acima, quando o app está rodando e acessado no http://domainname/ , um usuário irá receber “Hello, World!” como resposta.

 

Conectando o banco de dados com o Flask Python

 

 

Enquanto que o código acima representa um aplicativo Flask Python completo, ele não faz nada de interessante. Uma coisa coisa interessante que um aplicativo web consegue fazer é persistir o dado do usuário, mas para isso precisa da ajuda e conexão a um banco de dados.

 

O Flask Python é basicamente um framework do tipo “faça você mesmo”. Isso significa que não tem nenhuma interação interna com banco de dados, mas o pacote flask-sqlalchemy irá conectar o banco de dados SQL a um aplicativo Flask. O pacote flask-sqlalchemy precisa somente de uma coisa para se conectar o banco de dados SQL: o banco de dados URL.

 

Note que uma grande variedade dos sistemas de gerenciamento de banco de dados SQL podem ser utilizados com flask-sqlalchemy, desde que o DBMS tenha um intermediário que siga o padrão DBAPI-2. Nesse exemplo, nós utilizaremos o PostgreSQL, então o intermediário para falar com o banco de dados Postgres é o pacote psycopg2. Assegure que o pacote psycopg2 está instalado no seu ambiente e inclua ele na sua lista como pacotes necessário no setup.py. Você não precisa fazer mais nada com ele; o flask-sqlalchemy irá reconhecer o Postgres do banco de dados URL.

 

O Flask precisa que o banco de dados URL seja parte da sua configuração central através do atributo SQLALCHEMY_DATABASE_URI. Uma solução rápida e suja pra isso é fazer um hardcode do banco de dados dentro do aplicativo.

 

 

No entanto, essa não é uma solução sustentável. Caso troque de banco de dados ou não quer que seu banco de dados URL seja visível no seu source control, você terá que fazer mais coisas para garantir que sua informação é apropriada ao ambiente.

 

Você pode tornar as coisas mais simples utilizando variáveis de ambiente. Elas irão garantir que independente da máquina que você rode o código, ele irá sempre apontar na coisa certa, se essa coisa estiver configurada no ambiente que está sendo rodado. Ele também garante que, mesmo que você precise da informação para rodar o aplicativo, nunca irá aparecer como um valor hardcoded no source control.

 

No mesmo lugar que você declarou o FLASK_APP, declare um DATABASE_URL apontando para o lugar do seu banco de dados Postgres. O desenvolvimento tende a funcionar localmente, então aponte para o seu banco de dados local.

 

 

Agora em app.py inclua o banco de dados URL no seu aplicativo web.

 

 

E simplesmente dessa forma, o seu aplicativo agora tem uma conexão com um banco de dados.

 

Definindo objetos em Flask Python

 

 

Ter um banco de dados para estar conectado é um ótimo primeiro passo. Agora é hora de definir alguns objetos para preencher o banco de dados.

 

No desenvolvimento de aplicativos, um “model” refere-se a representação real ou conceitual de algum objeto. Por exemplo, caso esteja fazendo um app para uma concessionária de carros, você talvez defina um model chamado car que encapsule todos os atributos e comportamentos de um carro.

 

Nesse caso, você estará fazendo um To-do List com Tasks, e cada Task pertence a um usuário. Antes de você pensar mais a fundo sobre como eles estão relacionados, comece definindo os objetos para Tasks e Users.

 

O pacote flask-sqlalchemy aproveita o SQLalchemy para configurar e informar a estrutura do banco de dados. Você irá definir um modelo que irá viver no banco de dados herdando do objeto db.Model e irá definir o atributo desses models como instâncias db.Column. Para cada coluna, você deve especificar um tipo de dado, e então você irá passar esse data type para o comando db.Column como primeiro argumento.

 

Pelo fato da definição do model ocupar um espaço conceitual diferente do que da configuração do aplicativo, faça com que o models.py mantenha definições de model de forma separada do app.py. O modelo do Task deve ser construído para que tenha os seguintes atributos:

 

  • id: Um valor que é um identificador único para puxar do banco de dados.
  • name: O nome ou o título da task que o usuário irá ver quando task for listada.
  • note: Quaisquer comentários adicionais que uma pessoa queira deixar com sua task.
  • creation_date: A data e o horário que a task foi criada.
  • due_date: A data e o horário que a task deve ser concluída (se houver).
  • completed: Uma forma de indicar se a task foi concluída ou não.

 

Dado essa lista de atributos para objetos Task, o objeto Task do aplicativo pode ser definida dessa forma:

 

 

Note a extensão do método de construção de classe. No final do dia, qualquer model que você construa é ainda um objeto Python, portanto deve passar pela construção para que seja instanciado. É bom assegurar que a data de criação da instância do model reflita a sua verdadeira data de criação. Você pode explicitamente configurar esse relacionamento dizendo, “Quando uma instância desse model for criada, grave a data e o horário e configure como data de criação”.

 

 

Relacionamento dos models

 

Em certos aplicativos web, você talvez queira expressar relacionamentos entre objetos. No exemplo do To-do list, usuários são donos de várias tasks, e cada tarefa pertence a somente a um usuário. Esse é um exemplo de um relacionamento “many-to-one”, também conhecido como foreign key relationship, onde as tasks são os “many” (muitos) e o usuário dono delas é o “one” (um).

 

No Flask Python, um relacionamento many-to-one pode ser especificado utilizando a função db.relationship. Primeiro, construa o objeto User.

 

 

Parece bastante similar com o objeto Task; você irá descobrir que muitos objetos têm os mesmos formatos básicos de atributos de classe como tabelas de colunas. De vez em quando, você irá se deparar com algo um pouco diferente, incluindo a magia de herança múltipla, mas essa é a norma.

 

Agora que o model user está criado, você pode configurar o foreign key relationship. Para o “many”, configure campos para o user_id do user que é dono dessa task, também como o objeto user com essa ID. Também inclua um argumento de palavra-chave (back_populates) que atualiza o user model quando uma task recebe um usuário como dono.

 

Para o “one”, configure um campo para a task que o usuário específico é dono. Similar a manter o two-way relationship no objeto Task, configure um argumento de palavra-chave no campo de relacionamento do usuário para a atualizar a Task quando for vinculada a um usuário.

 

 

Inicializando o banco de dados

 

Agora que os modelos e os relacionamentos de modelos estão configurados, comece configurando o seu banco de dados. O Flask Python não vem com a sua própria utilidade de gerenciamento de banco de dados, então você terá que escrever o seu próprio (até um certo ponto). Você não precisa enfeitar muito; você só precisa de algo para reconhecer quais tabelas serão criadas e alguns códigos para criá-las (ou eliminá-las se for necessário). Caso você precise de algo mais complexo, como lidar com atualizações de tabelas de banco de dados (por exemplo, migrações de banco de dados), você talvez queira dar uma olhada em ferramentas como Flask Migrate ou Flask-Alembic.

 

Crie um script chamado initializedb.py próximo do setup.py para gerenciar o banco de dados. (Claro, não precisa ser chamado assim, mas porque não dar nomes que são apropriados a função do arquivo?) Dentro de initializedb.py, importe o objeto db de app.py e use-o para criar e eliminar tabelas. initializedb.py deve parecer dessa forma:

 

 

Se uma uma variável de ambiente de DEBUG estiver configurada, elimine as tabelas e reconstrua. Caso contrário, só crie as tabelas uma vez e você tá pronto pra começar.

 

Views e configuração de URL

 

As últimas partes necessárias para conectar o aplicativo inteiro são os views e routes. Em desenvolvimento web, um “view” (conceito) é uma funcionalidade que roda quando um ponto de acesso específico (“route”) é atingido. Esses pontos de acessos aparecem como URLs: caminhos para funcionalidade de um aplicativo que retornam um dado ou manipulam um dado que foi fornecido. As views são estruturas lógicas que tratam de pedidos HTTP específicos de um certo cliente e retornam uma resposta em HTTP para aquele cliente.

 

Em Flask, views aparecem como funções; por exemplo, consegue ver a view “hello world” ali em cima. Pra ser prático, vamos mostrar aqui novamente:

 

 

Quando o route do http://domainname/ é acessado, o cliente recebe a resposta, “Hello, world!”.

 

Com o Flask, uma função está marcada como um view quando é decorado pelo app.route. Por sua vez, o app.route adiciona na configuração central do aplicativo um mapa vindo da rota especificada para a função que é executada quando aquela rota é acessada. Você pode utilizar isso para começar a construir o resto do API.

 

Comece por um view que lida somente com solicitações get, e responda com o JSON representando todas os routes que serão acessíveis e os métodos que podem ser utilizados para acessar elas:

 

 

Considerando que você quer que seu view lide somente com um tipo de solicitação HTTP, utilize o app.route para adicionar essa restrição. O argumento de palavra-chave methods irá pegar uma lista de strings como valor, com cada string um tipo possível de método HTTP. Na prática, você pode utilizar app.route para restringir para um ou mais tipos de solicitações HTTP ou aceitar quaisquer solicitações deixando o argumento de palavra-chave methods sozinho.

 

O que quer que você queira retornar da sua função view deve ser um string ou objeto que o flask transforme em um string quando estiver construindo uma resposta corretamente formatada de HTTP. As exceções da regra estão quando você tenta lidar com redirections e e exceptions que são jogadas para você pelo seu aplicativo. Isso significa pra você, o desenvolvedor, que você deve ser capaz de encapsular quaisquer respostas que você está tentando mandar de volta para o cliente para algo que possa ser interpretado como um string.

 

Uma boa estrutura que contém complexidade, mas que mesmo assim pode ser transformada em um string é um dicionário Python. Portanto, eu recomendo, quando você quiser mandar dados para o cliente, você utilize um dict do Python com quaisquer key-value pairs que você precise para transmitir informação. Para transformar esse dicionário em uma resposta JSON com a formatação correta, headers e tudo mais, passe isso como argumento para a função do Flask jsonify.
(from flask import jsonify).

 

A função view encima pega o que é efetivamente uma lista de todo o route que esse API pretende lidar e envia ao cliente todas vez que o route http://domainname/api/v1 for acessada. Tenha em mente que, por si mesmo, o Flask oferece suporte ao roteamento para URLs exatamente iguais, então acessar essa rota com um trailing / iria criar um erro 404. Se você quisesse lidar com a mesma função view, você precisaria de um stack de decoradores dessa forma:

 

 

Seria interessante se o route definido tivesse um trailing slash e o cliente pedisse pelo route sem o slash, você não precisaria dobrar os decoradores. O Flask iria redirecionar a solicitação do cliente de forma adequada. É estranho que não funcione das duas maneiras.

 

Solicitações Flask e DB

 

Em base, o trabalho de um framework para desenvolvimento web é lidar com solicitações de entrada HTTP e retornar respostas HTTP. O view que foi escrito anteriormente não tem muito a ver com respostas HTTP tirando o URL que foi acessado. Não processa nenhum dado. Vamos ver como o Flask Python se comporta quando dados precisam ser manipulados.

 

A primeira coisa para se saber é que o Flask Python não fornece um objeto request separado para cada função view. Ele tem one (um) objeto de solicitação global que cada função view pode utilizar, e esse objeto é nomeado de forma conveniente de request e pode ser importado do pacote Flask.

 

A próxima coisa é que os padrões de routes do Flask podem ter um pouco mais de nuances. Uma ocasião é de uma route que foi hardcoded deve bater certinho para ativar uma função view. Uma outra ocasião seria um padrão de routes que conseguem lidar com uma variedade de rotas, todas mapeando para uma view permitindo que uma parte dessa route seja uma variável. Se a route em questão tiver uma variável, o valor correspondente pode ser acessado pela mesma variável nomeada na lista de parâmetros view.

 

 

Para comunicar com um banco de dados dentro de um view, você deve utilizar o objeto db que foi preenchido na parte superior do script. O seu atributo session é a sua conexão ao banco de dados quando você quiser fazer mudanças. Se você quiser simplesmente buscar por objetos, os objetos feitos do db.Model tem as suas próprias camadas de interação com banco de dados através do atributo query.

 

E finalmente, qualquer resposta que você quiser de um view que for mais complexa que um string deve ser construída de forma deliberada. Anteriormente você construiu uma resposta utilizando o dicionário “Jsonified”, mas algumas suposições foram feitas (por exemplo, 200 status code, status message “OK,” Content-Type of “text/plain”). Qualquer coisa especiall que você quiser em sua resposta HTTP deve ser adicionado por você manualmente.

 

Saber sobre essas coisas sobre trabalhar com views do Flask permite com que você construa um view cujo o seu trabalho é criar novos objetos task. Vamos dar uma olhada no código abaixo e comentar passo a passo.

 

 

Vamos começar com o decorador @app.route. O route é ‘/api/v1/accounts//tasks’, onde <username> é uma variável route. coloque colchetes angulares em qualquer parte do route que você quer que seja uma variável, e então inclua essa parte do route na próxima linha da lista de parâmetros com o mesmo nome. Os únicos parâmetros que devem estar na lista de parâmetros devem ser as variáveis de seu route.

 

O próximo seria o Query:

 

 

Para procurar por um usuário pelo username, conceitualmente você deve procurar por todos os objetos Users armazenados no banco de dados e encontrar todos os usuários que batem com o username que foi solicitado. Com Flask Python, você pode pedir o objeto User diretamente através do atributo query para a instância que bate o seu critério. Esse tipo de query forneceria uma lista de objetos (mesmo que seja um objeto ou nenhum), então para conseguir o objeto que você quer, simplesmente digite o comando first().

 

 

Sempre que o dado for enviado para o aplicativo, independente do método HTTP utilizado, esse dado é armazenado no atributo form do objeto request. O nome do campo no frontend será o nome da chave mapeada naquele dado no dicionário form. Sempre virá numa forma de string, então caso queira que seu dado seja um tipo específico de dado, você terá que torná-lo explícito convertendo-os para o tipo apropriado.

 

A outra coisa para ser observada é a atribuição do user ID do usuário para a nova Task instanciada. É assim que o foreign key relationship é mantido.

 

 

Criar uma nova instância Task é ótimo, mas a sua construção não tem nenhuma conexão inerente às tabelas dos bancos de dados. Para inserir uma nova linha na tabela SQL correspondente, você deve utilizar o session que está atrelado ao objeto db. O db.session.add(task) cria o terreno para a nova instância Task para ser adicionada a tabela, mas não adiciona ela ainda. Embora seja feito apenas uma vez aqui, você pode adicionar a quantidade de coisas que você quiser antes de fazer committing. O db.session.commit() pega todas as alterações testadas, ou faz “Commit”, e aplica elas para as tabelas correspondentes dos bancos de dados.

 

 

A resposta é uma instância verdadeira de um objeto Response com o seu mimetype, corpo e status configurado de forma deliberada. O objetivo dessa view é alertar o usuário que foi criado algo novo. Vendo como esse view é feito para fazer parte de um API backend que envia e recebe JSON, o corpo de resposta deve ser um JSON serializável. Um dicionário com uma simples mensagem string deve dar conta do trabalho. Garanta que esteja pronto para transmitir escrevendo o comando json.dumps no dicionário, no qual irá tornar o objeto Python num JSON válido. Isto é utilizado ao invés de jsonify, como jsonify constrói um objeto de resposta verdadeiro utilizando seu input como um corpo de resposta. Em contraste, json.dumps simplesmente pega um objeto Python e converte a um string JSON válido se for possível.

 

Por padrão, o código de status de cada resposta enviada com o flask será 200. Isso irá funcionar na maioria das circunstâncias, onde você não está tentando enviar de volta uma mensagem de redirecionamento de nível específico ou um erro de nível. Considerando que nesse caso deixa explicitamente o frontend saber quando um novo item for criado, configure o código de status para ser 201, que corresponde a criar algo novo.

 

Então é isso! Esse é o resumo para criar um novo objeto Task utilizando o Flask Python levando em consideração a configuração do seu to-do list do seu aplicativo. Views similares podem ser construídas para listamento, edição e deleção de tasks, mas isso te dá uma ideia de como poderia ser feito.

 

Conclusão Flask Python

 

 

Tem muita coisa que vai em um aplicativo do que simplesmente uma view para criar coisas. Embora ainda não tenha discutido sobre sistemas de autorização/autenticação, testing, database migration management, cross-origin resource sharing, etc, as informações citadas acima devem dar o suficiente para você começar a escavar para criar suas próprias aplicações flask python.

 

Artigo adaptado e inspirado de: https://opensource.com/article/18/4/flask

 

O que aprendemos nesse artigo?

 

O que é um framework?

Um framework é uma biblioteca de códigos que torna a vida do desenvolvedor mais fácil, quando se fala de aplicativos, escaláveis e fáceis de manter, fornecendo códigos reutilizáveis ou extensões para operações comuns.

Como você instala o Flask?

Igual às bibliotecas de python bastante utilizadas, o pacote Flask é instalável através do Python Package Index (PPI).

O que é um Model?

No desenvolvimento de aplicativos, um model refere-se a representação real ou conceitual de algum objeto.

O Flask vem com sua própria utilidade de banco de dados?

O Flask Python não vem com a sua própria utilidade de gerenciamento de banco de dados, então você terá que escrever o seu próprio até certo ponto.

 

 

Compartilhe com seus amigos!

Deixe um comentário