Buscar

Guia pratico Python&Flask

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 73 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 73 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 73 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Sumário
 
1. Sobre o Autor
2. Introdução
2.1. Para quem é esse livro?
2.2. Por que devo aprender Flask?
2.3. Fundamentos de execução
2.4. Como baixar o material desse livro
2.5. Convenções tipográficas
3. O que é o Flask
4. Configurações e Instalações 
4.1. Instalando o Python
4.2. Configurando o Python e as variáveis de ambiente
4.3. Criando um ambiente Flask
4.4. Instalando o Flask e seus recursos necessário
5. Criando seu primeiro WebApp
6. Estrutura de arquivos e pastas
7. Como funciona um projeto Flask de uma WebApp?
8. Como funciona uma rota?
9. O que é URL amigável?
10. Como funciona um template?
11. Recursos do Template
11.1. Usando uma variável no HTML
11.2. Usando IF no HTML
11.3. Usando FOR no HTML
12. Criando uma página de erro de rotas
13. Recuperando informações através do GET e POST
14. Criando e gerenciando sessões
14.1. O que é Secretkey?
14.2. Criando uma Sessão
14.3. Recuperando uma Sessão
14.4. Excluindo uma Sessão
14.5. Restrição de acesso usando Sessão
15. O que é um Dataset?
15.1. Criando uma conexão SQLite
15.2. Criando uma Tabela
15.3. Inserindo dados
15.4. Listando dados
15.5. Atualizando dados
15.6. Excluindo dados
16. O que é um Blueprint
17. Projeto WebApp – Pizzaria
17.1. Criando a página principal
17.2. Criando área de acesso para Clientes
17.3. Criando área de acesso para Gerentes
17.4. Criando área para cadastro de Pizzas
17.5. Criando área de Pedidos Clientes/Gerentes
18. Próximos passos
19. Agradecimento
19. 
1. Sobre o Autor
 
Meu nome é Wallace Fragoso sou Desenvolvedor Web e Mobile, com mais
de 10 anos de experiência na área de informática, formado em Análise de
Sistemas pela Estácio de Sá em Natal/RN, pós-graduado em Engenharia de
Software pela UFRN, professor e fundador do site DevAcademy que é um
projeto destinado a compartilhar conhecimento e formar novos profissionais.
 
Me encontre:
Facebook: https://facebook.com/devacademybr
Instagram: https://www.instagram.com/wallacefragoso
E-mail: devacademybr@gmail.com
 
2. Introdução
 
O Flask é um microframework para a criação de sites ou sistemas web, é
considerado um microframework porque mantêm um núcleo simples. Não há
uma camada de abstração do banco de dados, validação de formulários, ou
qualquer outro componente, porém possui bastantes bibliotecas de terceiros
que provem uma gama de funcionalidades.
 
Nesse livro vamos entender os conceitos e estruturas desse framework
incrível, vamos ter um aprendizado focada nas principais funcionalidades
disponíveis na sua documentação, abordando desde sua instalação, sintaxe e
seus principais recursos, dando a você a capacidade de construir um site ou
sistema em poucos minutos!
 
2.1 Pra quem é esse livro?
 
Esse livro é destinado a todos os desenvolvedores Python que querem
expandir seus conhecimentos e levá-lo a outro nível, permitindo assim
utilizar todos os recursos do Python em aplicações Web.
 
2.2 Por que devo aprender Flask?
https://facebook.com/devacademybr
https://www.instagram.com/wallacefragoso
mailto:devacademybr@gmail.com
 
O Flask é um Framework minimalista que te ajudar a conhecer os principais
padrões de frameworks mais complexo com a vantagem de ser bem
simplificado, além disso é a porta de entrada para frameworks mais robustos
como Django.
 
2.3 Fundamento de execução
 
As primeiras etapas desse livro tem como objetivo principal apresentar a
criação e estrutura do projeto e apresentar a sintaxe dos principais recursos
desse framework, em seguida teremos os conceitos acompanhado de códigos
de fácil aplicação e, por fim, criaremos um projeto completo usando todo o
conhecimento adquirido para criar um WebApp.
 
2.4 Como baixar o material desse curso
 
Todo material desse curso poderá ser encontrado nesse LINK
 
 
2.5 Convenções tipográficas
 
Com a finalidade de destacar diferentes tipos de informações neste livro estou
adotando uma convenção que será apresentada a seguir:
 
Marcação e scripts
Os scripts serão trazidos com estilos de fontes diferentes acompanhadas de
sua respectiva página.
Em alguns casos teremos destaques em negrito, direcionando a informação
principal abordado.
E por fim uma lista com as informações de cada linha comentada.
 
1. # coding: utf-8
2. from flask import Flask
3.
4. app = Flask(__name__)
5.
https://drive.google.com/open?id=1Sijoo8pYgtI0QqFvxfzJRwE8C5uUg7qQ
6. @app.route("/")
7. def ola_mundo():
8. return "Olá Mundo! Esse é meu primeiro WebApp!", 200
9.
10. app.run()
 
Linha 4: Iniciando o framework Flask.
 
3. O que é Flask?
 
Flask tem a flexibilidade da linguagem de programação Python e provê um
modelo simples para desenvolvimento web. Uma vez importando no Python,
Flask pode ser usado para economizar tempo construindo aplicações web.
 
É chamado de microframework porque mantêm um núcleo simples mas
estendível. Não há uma camada de abstração do banco de dados, validação de
formulários, ou qualquer outro componente onde bibliotecas de terceiros
existem para prover a funcionalidade. Assim, Flask suporta extensões
capazes de adicionar tais funcionalidades na aplicação final. Há uma vasta
coleção de bibliotecas para resolver essas questões em Python, isso simplifica
o framework e torna sua curva de aprendizado mais suave.
 
4. Configurações e Instalações
 
Existe uma série de recursos que você precisa ficar atento para que funcione
corretamente em seu computador. Neste livro vamos utilizar os comandos e
configurações padrão para o Windows, porém você consegue facilmente
encontrar essa informação para o Linux / Mac.
 
4.2 Configurando o Python e as variáveis de
ambiente
 
Caso você não tenha o Python instalado na sua máquina:
 
Baixe o executável de instalação do Python nesse LINK;
https://www.python.org/download/releases/2.7/
Faça a instalação seguindo os passos necessários;
Em seguida instale o PIP caso não esteja instalado, nesse LINK;
Caso não consiga instalar nesse link, pesquise como instalar PIP no
Python 2.7
 
Por que vamos utilizar o Python 2.7?
Os principais plugins que é utilizado hoje em dia estão na versão 2.7, porém
caso você entenda que a versão 3.x é melhor para sua realidade você pode
executar os mesmos comandos que tudo deve funcionar normalmente.
 
4.3. Criando um ambiente Flask
 
Antes de prosseguir vamos instalar o virtualenv que é usado para isolar o
ambiente do Flask, para isso entre no CMD do Windows / Terminal do
Linux/MacOS e faça a instalação usando o seguinte comando:
 
python.exe -m pip install virtualenv
 
Aguarde a instalação e vamos configurar o ambiente de fato, seguindo os
seguintes passos:
 
Primeiro crie uma pasta no local onde deseja criar o projeto;
Entre na pasta que você acabou de criar;
Crie 2 arquivos nessa pasta: __init__.py e app.py
Execute o seguinte comando: C:\Python27\Scripts\virtualenv.exe
nome_do_projeto_env
Após terminar de criar o ambiente você deve ir na pasta e ativar o
ambiente da seguinte forma: nome_do_projeto_env\Scripts\activate
Caso o comando tenha sido realizado com sucesso você deve ver o
terminal da seguinte forma: (nome_do_projeto_env)
seuuser@suamaquina/path/to/pasta$
Por fim, instale o Flask: pip install Flask
 
 
Agora vamos seguir esses passos para criar nosso primeiro projeto:
 
md Projeto01
http://cyz.github.io/python/2016/09/02/instalando-o-pip-no-windows.html
cd Projeto01
. > __init__.py
. > app.py
C:\Python27\Scripts\virtualenv.exe pj1_env
pj1_env\Scripts\activate
 
Seu terminal deve ficar assim:
(pj1_env) C:\Users\seu\caminho\aqui\projeto01>
 
E instale o Flask
pip install Flask
 
5. Criando seu primeiro WebApp
 
Já temos nosso ambiente configurado e vamos executar o nosso primeiro
WebApp da seguinte forma:
 
Abrar o arquivo que criamos com seu editor de código preferido;
Escreva o seguinte código:
 
1. # coding: utf-8
2. from flask import Flask
3.
4. app = Flask(__name__)
5.
6. @app.route("/")
7.def ola_mundo():
8. return "Olá Mundo! Esse é meu primeiro WebApp!", 200
9.
10. app.run()
 
 
Entendendo a nossa primeira aplicação web:
Linha 1 – Definimos a codificação do texto em utf-8 (Padrão para acentuação
Brasileira)
Linha 2 – É a importação do framework Flask
Linha 4 – É a criação do nosso aplicativo Web, e passamos como parâmetro o
nome do projeto em questão, que nesse caso estamos utilizando uma variável
de ambiente para carregar o nome do arquivo. Se preferir use app =
Flask(“projeto01”).
Linha 5 – É um decorator para definirmos a rota dessa função, nesse caso é a
nossa index.
Linha 7 – Criamos uma função simples em Python para atribuir a nossa rota,
ou seja, ao iniciar o projeto web essa função será chamada.
Linha 8 – É o resultado que será apresentado na nossa página principal da
nossa aplicação web.
Linha 10 – Agora que a nossa aplicação está pronta, podemos “rodá-la”
usando o comando app.run()
 
Para executar nossa primeira página, vamos no terminal e executamos o
arquivo app.py:
 
(pj1_env) C:\Users\seu\caminho\aqui\projeto01> python app.py
 
E deve apresentar a seguinte mensagem:
 
* Serving Flask app "app" (lazy loading)
* Environment: production
 WARNING: Do not use the development server in a production
environment.
 Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 
Copie o endereço que foi impresso no terminal e cole-o no seu navegador, e
você deve ver sua primeira aplicação em pleno funcionamento!
 
E se quiser parar a aplicação para fazer qualquer alteração, você vai até o
terminal que está com essa mensagem e pressione CTRL (Comand) + C,
como está apresentado no terminal.
 
 
6. Estrutura de arquivos e pastas
 
A estrutura básica de todo projeto deve seguir da seguinte forma:
/Pasta_do_Projeto
 /app.py
 /templates/*
 /static/*
 /media_files/*
 
Pasta_do_Projeto – É a pasta raiz do projeto
app.py – É o arquivo padrão e de execução do projeto
templates – É uma pasta destinada a organizar todos os arquivos com
extensão html
static – É a pasta destinada a inserção de arquivos javascript (.js) e folhas de
estilos (.css)
media_files – É a pasta destinada a organização de arquivos de mídias.
 
 
7. Como funciona um projeto Flask de uma
WebApp?
 
Como já sabemos o framework Flask é bem simples e com poucos recursos e
ele se utiliza de alguns plugins para gerenciar seus recursos, são eles:
 
WerkZeug – Um dos recursos mais importantes, é uma biblioteca
destinada a criar uma interface entre o Python e o Web Server. Ela
possui a implementação básica de padrões para interceptar requests e
lidar com response, controle de cache, cookies, HTTP, roteamento de
urls.
Jinja2 – É um template engine utilizado para renderizar os recursos do
HTML e interpretar marcações entre coxetes e executá-los como se
fosse em Python. Ele vem com a implementação da maioria dos
recursos necessários na construção de templates html e facilita a
customização de template filters, macros e muito mais.
WSGI – É uma implementação de Web Server que usa como base o
Apache.
 
 
 
 
8. Como funciona uma rota?
 
As rotas são uma parte crucial de toda aplicação web, e neste caso não é
diferente, elas são usadas para associar o que digitamos no URL da página
com uma função do nosso framework.
Para isso utilizamos o decorator @app.router(), e passamos como parâmetro
o verificador da URL:
 
@app.router(“/”)
def inicio()
 
Isso quer dizer que ao acessar a raiz do projeto o framework deve chamar a
function inicio(), ao acessar a URL http://127.0.0.1:5000/.
 
@app.router(“/casa/”)
def casa()
 
Neste outro exemplo, ao acessar a URL http://127.0.0.1:5000/casa o
framework vai entender que você quer acessar a function casa().
 
Uma das maiores vantagens do Flask é a utilização de URLs de fácil leitura,
permitindo assim que os usuários lembre-se sempre da rota correta, além
disso podemos associar facilmente o nome da URL com nossas functions.
 
9. O que é URL amigável?
 
URLs amigáveis são aquelas de fácil compreensão tanto para usuários e
quanto para os buscadores, você bate olho e entende do que trata a página, e é
muito mais convidativa a ser clicada e memorizada e gerando assim mais
segurança.
 
Todas as páginas que criamos utilizado esse framework utiliza-se o endereço
padrão de acesso que é gerado ao iniciar o projeto no terminal, a partir desse
endereço padrão todas as nossas páginas ganham uma extensão que pode ser
/casa, /carro, /cadastro, etc.
 
Algumas recomendações ao criar URL amigáveis:
Não usar acentos, símbolos e caracteres diferentes como ç;
As palavras devem ser separadas por hífen (-);
Use letras minúsculas;
Sempre que possível inclua palavra-chave;
Deve ser mais curta possível.
 
10. Como funciona um template?
 
Os Templates são modelos em HTMLs que criamos e podemos utilizá-los em
nosso projeto, porém gerar HTML no Python não é nada divertido, na
verdade, é bastante trabalhoso, porque você precisa fazer o HTML não ter
problemas de caracteres epeciais que podem gerar erros ao serem lidos pelo
Python. Por causa disso, o Flask configura o mecanismo do modelo Jinja2
para você automaticamente.
 
Para renderizar um modelo, você pode usar o método render_template().
Tudo o que você precisa fazer é fornecer o nome do modelo e as variáveis
que deseja passar para o mecanismo de modelo como argumentos de palavra-
chave.
 
Sempre que utilizar o render_template certifique-se de criar uma pasta
chamada templates na raiz do projeto, e adicionar seu arquivo HTML dentro
desta pasta.
 
No nosso exemplo, precisamos criar o arquivo
templates/modelo_template.html:
 
1. <html>
2. <body>
3. <p>
4. Iniciando o modelo de template através do método
<b>render_template</b>
5. </p>
6. </body>
7. </html>
 
Agora abra o arquivo (app.py) do nosso projeto e faça a seguinte adição:
 
…
2. from flask import Flask, render_template
…
10. @app.route("/modelo/")
11. def modelo():
12. return render_template("modelo_template.html"), 200
…
 
Linha 2: Vamos fazer a importação do método render_template.
Linha 10: Vamos adicionar a rota para a adição de uma nova página /modelo.
Linha 11: Criamos a function modelo() para ser direcionado pela URL.
Linha 12: Em vez de utilizarmos apenas um texto, vamos apontar como
parâmetro do render_template a nossa página em HTML.
 
OBS.: Para que o código funcione corretamente vamos precisar reiniciar o
nosso servidor pelo terminal, utilizando o comando CTRL + C e depois
executando o nosso arquivo novamente.
 
Baixe esse projeto nesse LINK.
 
11. Recursos do Template
 
Uma das vantagens de utilizar o Flask é a possibilidade de usarmos todos os
recursos e métodos do Python, esses recursos podem ser usados de várias
maneiras e vamos detalhar nesse capítulo.
 
11.1. Usando uma variável no HTML
 
As variáveis são os principais recursos do Python, e podemos utilizá-los em
nosso HTML, passando valores das nossas functions ou diretamente na
página:
 
Vamos ver o arquivo templates/modelo_variavel.html:
 
1. <html>
2. <body>
3. <p>
4. Iniciando o modelo de template passando algumas <b>variáveis</b><br>
5. Meu nome: <b>{{ nome }}</b>
6. </p>
7. </body>
8. </html>
 
Linha 5: Vamos recuperar a variável nome, que deve vir do nosso método
render_template, que se encontra no arquivo principal do projeto.
 
 
No nosso arquivo principal app.py:
…
14. @app.route("/variavel/")
15. def variavel():
16. meu_nome = "Wallace Fragoso"
17. return render_template("modelo_variavel.html", nome=meu_nome),
200
…
 
Vamos criar uma rota para testarmos esse recurso.
 
Linha 16: Criamos uma variável que só pode ser vista dentro do nosso
método, e atribuímos a ele um valor, nesse caso utilizamos uma string com o
meu nome.
Linha 17: No método render_template, podemos adicionar além da origem
da página, uma ou mais variável para ser carregada nesta página. Cada
variável deve ser separada por vírgula.
 
Acesse essa página através da URL http://127.0.0.1:5000/variavel/ e será
possível ver o resultado.
 
É importante saber que existem alguns tipos de delimitadores.Os delimitadores Jinja padrão são configurados da seguinte maneira:
 
{% %} Utilizada nas declarações.
{{ }} Utilizada para imprimir a saída do modelo.
{# #} Utilizada nos comentários, não são incluídos na saída do
modelo.
 
No arquivo modelo_variavel.html faça os seguintes testes, adicione os
seguintes trechos:
 
Soma: {{ (3+4) }} <br>
Subtração: {{ (3-4) }} <br>
Divisão: {{ (12/4) }} <br>
Multiplicação: {{ (3*4) }} <br>
 
Ao adicionar esses trechos diretamente na página você vai perceber que
foram realizadas as operações diretamente na página, sem a necessidade de
criar variáveis.
 
Para ver a lista completa de tudo que é possível fazer nas páginas de
templates, acesse o LINK com a documentação do jinja2.
 
11.2. Usando IF no HTML
 
Agora que vimos como criar variáveis e acessá-las no nosso template, vamos
a outro recurso de fundamental importância, o condicional IF e ELSE:
 
No nosso aquivo principal app.py:
…
19. @app.route("/condicional/")
20. def condicional():
21. return render_template("modelo_condicional.html"), 200
…
 
Agora vamos ver o arquivo templates/modelo_condicional.html:
1. <html>
2. <body>
http://jinja.pocoo.org/docs/2.10/templates/
3. <p>
4. Iniciando o modelo de template utilizando <b>condicional IF e ELSE</b>
<br>
5. 3 é maior do que 5? <br>
6. {% if (3 > 5): %}
7. Sim <br>
8. {% else %}
9. Não <br>
10. {% endif %}
11. </p>
12. </body>
13. </html>
 
Linha 6: Iniciamos a verificação da condição IF.
Linha 7: Se o resultado for positivo, ou seja, se 3 for maior do que 5.
Linha 8: A condicional else.
Linha 9: Se o resultado for negativo, ou seja, se 3 NÃO for maior do que 5.
Linha 10: E por fim, o fechamento da verificação da condição IF.
 
Acesse essa página através da URL http://127.0.0.1:5000/condicional/ e será
possível ver o resultado.
 
11.3. Usando FOR no HTML
 
Agora que vimos como criar variáveis e o IF ELSE no condicional, vamos a
outro recurso do template, a repetição FOR:
 
No nosso aquivo principal app.py:
 
…
23. @app.route("/repeticao/")
24. def repeticao():
25. return render_template("modelo_repeticao.html"), 200
…
 
Agora vamos ver o arquivo templates/modelo_repeticao.html:
1. <html>
2. <body>
3. <p>
4. Iniciando o modelo de template utilizando a repetição <b>FOR</b><br>
5. {% for i in range(1,5): %}
6. {{ i }} <br>
7. {% endfor %}
8. </p>
9. </body>
10. </html>
 
Linha 5: Iniciamos a repetição FOR, e usando a função RANGE do Python
para criar uma sequência.
Linha 6: Vamos imprimir o valor sequencial que criamos no RANGE.
Linha 7: Finalizamos a repetição FOR.
 
Acesse essa página através da URL http://127.0.0.1:5000/repeticao/ e será
possível ver o resultado.
 
 
12. Criando uma página de erro de rotas
 
Em muitos casos precisamos tratar rotas que não foram mapeadas, para uma
pessoa que esteja acessando seu site é uma experiência muito ruim se deparar
com uma página de erro, porém podemos suavizar essa experiência em nosso
projeto.
 
No nosso aquivo principal app.py:
 
…
27. @app.errorhandler(404)
28. def nao_encontrado(error):
29. return render_template('nao_encontrado.html'), 404
…
 
Linha 27: Vamos utilizar o decorate @app.errorhandler(404) para tratar e
direcionar toda página que o usuário digitou na URL e não foi encontrada em
nosso projeto, e enviá-lo para uma página informando que o que foi digitado
não existe.
 
Agora vamos ver o arquivo templates/nao_encontrado.html:
 
1. <html>
2. <body>
3. <h1>Hum...</h1>
4. <p>Os nossos duendes não encontrou a página solicitada.</p>
5. </body>
6. </html>
 
Agora para testarmos o resultado vamos acessar a página digitando qualquer
URL que não exista em nosso projeto, como, por exemplo,
http://127.0.0.1:5000/usuario/ e veremos o resultado.
 
13. Recuperando informações através do GET e
POST
 
As requisições são envios de informações entre páginas, esses envios podem
ser visíveis (GET) ou invisíveis (POST) para a página solicitante.
 
Normalmente essas requisições são utilizadas por form ou formulários, e
neles podemos definir o método de envio (method) e os dados que serão
enviados, esses dados são identificados através das entradas de dados, que
podem ser inputs com os atributos name e value preenchidos.
 
Para facilitar o entendimento deste capítulo, vamos criar um novo projeto
para reforçar o aprendizado no que diz respeito a criação de projetos.
 
Lembre-se de sair do projeto atual para podermos criar esse novo projeto.
Vamos criar esse projeto da seguinte forma:
md ProjetoGetPost
cd ProjetoGetPost
. > __init__.py
. > app.py
C:\Python27\Scripts\virtualenv.exe pjgp_env
pjgp_env\Scripts\activate
 
E instale o Flask
pip install Flask
 
Agora vamos ajustar esse nosso projeto, abra o arquivo app.py:
 
1. # coding: utf-8
2. from flask import Flask, render_template, request
3.
4. app = Flask(__name__)
5.
6. @app.route("/")
7. def index():
8. return render_template("index.html"), 200
9.
10. @app.route("/form_get/")
11. def form_get():
12. return render_template("formulario_get.html"), 200
13.
14. @app.route("/form_post/")
15. def form_post():
16. return render_template("formulario_post.html"), 200
17.
18. @app.route("/resultado/", methods=['GET','POST'])
19. def resultado():
20. if request.method == "GET":
21. return "Get", 200
22. elif request.method == "POST":
23. return "Post", 200
24. else:
25. return "Não definido", 200
26.
27. app.run()
 
 
Vamos entender alguns pontos desse novo projeto:
Linha 2: Além de importar os recursos necessários do Flask, vamos importar
o request, que é o método responsável das detecções das requisições.
Linha 18: Vamos utilizar o decorate @app.route para definir a rota de
recuperação das requisições e vamos detectar o tipo de requisição, se é Get ou
Post.
 
Agora vamos explorar os arquivos HTML.
 
 
Abrindo o arquivo templates/index.html:
 
1. <html>
2. <body>
3. <h1>Início Projeto Get e Post</h1>
4. <ul>
5. <li> <a href="{{ url_for('form_get') }}">Exemplo Get</a> </li>
6. <li> <a href="{{ url_for('form_post') }}">Exemplo Post</a> </li>
7. </ul>
8. </body>
9. </html>
 
Linha 5 e 6: Um truque bem legal para gerar a URL do nosso projeto é
utilizar o recurso url_for, que monta completamente a URL baseando-se na
rota do nosso projeto.
 
Abrindo o arquivo templates/formulario_get.html:
 
1. <html>
2. <body>
3. <h1>Formulário GET</h1>
4. <form method="get" action="{{ url_for('resultado') }}">
5. Nome: <input name="nome"/> <br/>
6. Idade: <input name="idade"/> <br/>
7. <button>Enviar</button>
8. </form>
9. </body>
10. </html>
 
Linha 4: Utilizando o elemento em HTML form, vamos definir o método para
GET e a action ou a ação do formulário para onde os dados serão enviados.
Linha 5: O elemento em HTML input vai ser utilizado para montar o dado do
nome.
Linha 6: O elemento em HTML input vai ser utilizado para montar o dado da
idade.
 
Abrindo o arquivo templates/formulario_post.html:
 
1. <html>
2. <body>
3. <h1>Formulário POST</h1>
4. <form method="post" action="{{ url_for('resultado') }}">
5. Nome: <input name="nome"/> <br/>
6. Idade: <input name="idade"/> <br/>
7. <button>Enviar</button>
8. </form>
9. </body>
10. </html>
 
Linha 4: Utilizando o elemento em HTML form, vamos definir o método para
POST e a action ou a ação do formulário para onde os dados serão enviados.
Linha 5: O elemento em HTML input vai ser utilizado para montar o dado do
nome.
Linha 6: O elemento em HTML input vai ser utilizado para montar o dado da
idade.
 
 
Agora vamos ver a diferença entre elas:
 
Como o projeto ativo, acesso a seguinte URL
http://127.0.0.1:5000/form_get/.
 
Você vai ver o formulário com os dados do Nome e Idade, preencha elas e
clique no botão ENVIAR.
 
http://127.0.0.1:5000/form_get/
Vou preenchê-los com os seguintes dados:
Nome: Livro Python Flesk
Idade: 1
 
Ao clicar no botão enviar ele vai apresentar as seguintes informações:
 
Ele vai apontar para a URL que preenchemos no ACTION do FORM;
A URL deve ficar assim: http://127.0.0.1:5000/resultado/?
nome=Livro+Python+Flesk&idade=1
E terá uma mensagem na tela: GET
 
Agora vamos entender o que aconteceu:Ao enviar os dados, eles foram capturados pela página resultado que
ajustamos no arquivo app.py, no método resultado() adicionamos um
verificador para identificar que tipo de METHOD foi enviado para essa
página. Nesse caso, ele identificou que o METHOD enviado foi o GET, e por
isso ele mostrou exatamente o que queríamos. Por fim, a URL mostra
exatamente o que enviamos pelo nosso formulário, identificando o nome e a
idade atribuindo os valores que definirmos na página form_get.
 
Agora vamos fazer o mesmo com o POST na URL
http://127.0.0.1:5000/form_post/.
 
Vou preenchê-los com os mesmos dados:
Nome: Livro Python Flesk
Idade: 1
 
E vamos ver as diferenças ao clicar no botão enviar:
 
Ele vai apontar para a URL que preenchemos no ACTION do FORM;
A URL deve ficar assim: http://127.0.0.1:5000/resultado/
 
E terá uma mensagem na tela: POST
 
Para que possamos ver o resultado igual que vimos no GET vamos fazer a
seguinte alteração no arquivo app.py:
http://127.0.0.1:5000/resultado/?nome=Livro+Python+Flesk&idade=1
http://127.0.0.1:5000/resultado/?nome=Livro+Python+Flesk&idade=1
http://127.0.0.1:5000/form_post/
http://127.0.0.1:5000/resultado/?nome=Livro+Python+Flesk&idade=1
 
Na linha 23 altere essa linha para
 
22. elif request.method == "POST":
23. nome = request.form["nome"]
24. idade = request.form["idade"]
25. return "Nome: {} - Idade: {}<br>Post".format(nome, idade), 200
26. else:
 
Agora sim, você será capaz de ver o resultado do que enviamos do
formulário.
Outra opção que podemos utilizar em nossos projetos que foge desses dois
métodos é a passagem de parâmetros via URL. Esse recurso é muito utilizado
em API e bastante usado em vários projetos Flask, um exemplo de URL é
http://127.0.0.1:5000/api/v1/listar/1, agora vamos entender e saber como
podemos construir e recuperar essas informações:
 
No mesmo arquivo vamos criar nossa função para recuperar essa informação:
 
…
29. @app.route("/api/")
30. @app.route("/api/<versao>/")
31. @app.route("/api/<versao>/<metodo>/")
32. @app.route("/api/<versao>/<metodo>/<pagina>/")
33. def api(versao = None, metodo = None, pagina = None):
34. return "Versao: {}<br> Metodo: {}<br> Página:
{}".format(versao, metodo, pagina), 200
…
 
Linha 29, 30, 31 e 32: Vamos ajustar as rotas para receber todos os valores
que possamos pela URL e identificar qual informação estamos recebendo.
Linha 33: Vamos criar a função que corresponde a rota da API e atribuir os
parâmetros de cada valor que esperamos ter.
Linha 34: Agora vamos ver o resultado na tela, usando a function format do
Python para organizar melhor os dados.
 
Agora veja o resultado acessando a URL http://127.0.0.1:5000/api/v1/listar/1.
http://127.0.0.1:5000/resultado/v1/listar/1
http://127.0.0.1:5000/api/v1/listar/1
 
É possível também estabelecer esses parâmetros com os seguintes tipos:
 
string (padrão) Aceita qualquer tipo de texto sem barras (/)
int Aceita inteiros positivos (1, 2l, 100, etc ...);
float Aceita pontos flutuantes positivos (13.1, 11.2, etc ...);
path Assim como string, porém aceita barras (/local/da/pasta);
uuid Aceita strings do tipo UUID (89c27436-d64d);
 
 
14. Criando e gerenciando sessões
 
Sessões são uma forma simples de armazenar dados para usuários individuais
usando um ID de sessão único. Elas podem ser usadas para persistir
informações entre requisições de páginas e são enviados ao navegador
através de cookies de sessão e o ID, que pode ser usado para recuperar dados
da sessão existente. Caso uma ID ou cookie de sessão não exista, isso
significa que podemos criar uma nova sessão e gerar um novo ID de sessão.
 
O principal uso das sessões é compartilhar dados entre páginas de um mesmo
projeto, assim você não precisa ficar solicitando sempre ao banco de dados.
Um dos usos mais clássicos da sessão é a restrição de acesso às algumas
páginas, validadas pelo tipo do usuário, vamos ver um exemplo assim neste
capítulo.
 
14.1. O que é Secretkey?
 
Uma parte importante das sessões são o seu segredo, e por isso precisamos
cuidar muito bem desses dados que ficam expostos em nossas páginas, e para
evitar que qualquer um acesse essa informação o Flask exige que você crie
uma chave que será usada por ele para encriptar os dados que são
armazenados. Essa chave é usada como uma assinatura eletrônica por ele para
manipular facilmente os dados.
 
Essa chave pode ser criada como você preferir, por exemplo, você pode
querer escrever seu nome, seu aniversário, nome do seu cachorro ou uma
sequência de números/letras que formam uma frase, ou simplesmente criar
uma chave usando um gerador em MD5.
 
Antes de prosseguir vamos criar um novo projeto para explorarmos esses
recursos:
 
md ProjetoSession
cd ProjetoSession
. > __init__.py
. > app.py
C:\Python27\Scripts\virtualenv.exe pjss_env
pjss_env\Scripts\activate
 
E instale o Flask
pip install Flask
 
Agora vamos ajustar esse nosso projeto, abra o arquivo app.py:
 
1. # coding: utf-8
2. from flask import Flask, session
3.
4. app = Flask(__name__)
5. app.secret_key = 'MINHA_CHAVE_SECRETA' # nessário para a
criação da sessão
6.
7. @app.route('/')
8. def index():
9. return "Olá Sessão", 200
10.
11. app.run()
 
Linha 2: Vamos importar o nosso framework Flask e a session para podermos
utilizá-la.
Linha 5: Vamos criar a assinatura do projeto, no meu caso eu apenas escrevi
um texto, porém é recomendado que crie algo único para cada projeto.
 
Para que possamos entender melhor o gerenciamento da sessão, vamos fazer
algumas alterações no nosso arquivo principal para realizar as verificações
necessárias.
Então precisamos que o arquivo app.py esteja da seguinte forma:
 
1. # coding: utf-8
2. from flask import Flask, request, redirect, session, url_for
3.
4. app = Flask(__name__)
5. app.secret_key = 'MINHA_CHAVE_SECRETA' # nessário para a criação
da sessão
6.
7. @app.route('/')
8. def index():
9. html = '''<h1>Bem vindo ao Projeto Sessão</h1><p>Essa é a tela
principal, logo abaixo veremos se você está <i>Logado</i></p>'''
10.
11. if 'usuario' in session:
12. return html + '<p>Parabéns! Você está logado com o usuário {}.
<a href="{}">Sair</a></p>'.format(session['usuario'],url_for('logout'))
13. return html + '<p>Você não está logado, por favor acesse a área de <a
href="'+ url_for('login') +'">Login</a>.</p>'
14.
15. @app.route('/login', methods=['GET', 'POST'])
16. def login():
17. if request.method == 'POST':
18. session['usuario'] = request.form['usuario']
19. return redirect(url_for('index'))
20. return '''
21. <form method="post">
22. Usuário: <input type=text name=usuario> <br>
23. <input type=submit value=Entrar>
24. </form>
25. '''
26.
27. @app.route('/logout')
28. def logout():
29. session.pop('usuario', None)
30. return redirect(url_for('index'))
31.
32. app.run()
 
14.2. Criando uma Sessão
 
Ao configurar o projeto com a assinatura eletrônica e importar a session
podermos começar a manipular a sessão:
 
…
15. @app.route('/login', methods=['GET', 'POST'])
16. def login():
17. if request.method == 'POST':
18. session['usuario'] = request.form['usuario']
19. return redirect(url_for('index'))
20. return '''
21. <form method="post">
22. Usuário: <input type=text name=usuario> <br>
23. <input type=submit value=Entrar>
24. </form>
25. '''
…
 
Nesse trecho de código estamos gerenciando a tela de login, caso o acesso a
essa página seja feita através de uma requisição POST, entendemos que
precisamos cadastrar o nosso usuários, caso contrário entendemos que não
existe usuário logado e por isso precisamos mostrar um formulário para que
ele possa logar.
 
Linha 18: Nessa linha criamos a nossa sessão, neste caso estamos criando
uma sessão chamada usuario e nele vamos cadastrar o nome do usuário que
foi enviada pelo formulário.
 
A variável de sessão pode armazenar qualquer tipo de dado, seja texto
simples à tuplas
 
14.3. Recuperando uma Sessão
 
Para recuperar uma sessão, utilizamos o mesmo parametro do que usamos
para cadastra-lo,no nosso caso vamos recuperar a informação do usuario que
foi armazenada no ato do login:
 
…
7. @app.route('/')
8. def index():
9. html = '''<h1>Bem vindo ao Projeto Sessão</h1><p>Essa é a tela
principal, logo abaixo veremos se você está <i>Logado</i></p>'''
10.
11. if 'usuario' in session:
12. return html + '<p>Parabéns! Você está logado com o usuário
{}. <a href="{}">Sair</a>
</p>'.format(session['usuario'],url_for('logout'))
13. return html + '<p>Você não está logado, por favor acesse a área de <a
href="'+ url_for('login') +'">Login</a>.</p>'
…
 
Linha 11: Vamos fazer uma verificação, e ver se na sessão existe o parâmetro
que criamos, se ele existir então prossiga.
Linha 12: Caso nossa sessão exista e tenha alguma informação, então vamos
exibi-la, e neste caso vamos dar a opção do usuário encerrar a sessão.
 
14.4. Excluindo uma Sessão
 
Para excluir a sessão, basta removê-la usando o comando pop():
 
…
27. @app.route('/logout')
28. def logout():
29. session.pop('usuario', None)
30. return redirect(url_for('index'))
…
 
Linha 29: Vamos remover a sessão atual do usuário e em seguida
redirecionamos para a tela principal.
 
14.5. Restrição de acesso usando Sessão
 
Agora vamos criar uma área com restrição:
 
…
31.
32. @app.route('/restrito')
33. def restrito():
34. if 'usuario' in session:
35. return 'Olá {}, <br> Você está autorizado a acessar está
área.'.format(session['usuario'])
36. return redirect(url_for('index'))
37.
…
 
Hora de testar, primeiro execute o projeto:
 
python app.py
 
Acesse na URL http://127.0.0.1:5000/
 
Você vai ver que não existe sessão, vamos clicar no link em Login.
 
Coloque o seu nome.
 
Assim que você clicar em entrar você será levado para a tela principal com o
seu nome ativo.
 
Agora clique no link sair.
 
Agora tente acessar a URL que criamos a restrição
http://127.0.0.1:5000/restrito.
 
Você será redirecionado para a página principal, pois você não está logado.
http://127.0.0.1:5000/
http://127.0.0.1:5000/restrito
 
Agora faça o login novamente e tente acessar a área do restrito.
 
Agora sim você será capaz de ver essa tela, pois você está autorizado a
acessar essa área.
 
15. O que é um Dataset?
 
Um dos melhores recursos de todo site ou sistema, é ter a possibilidade de
armazenar informações, e usá-las para potencializar nossos objetivos. E Para
poder armazenar informações, precisamos guardá-las em algum lugar, e o
mais comum é usarmos Bancos de Dados.
 
Bancos de dados ou bases de dados são um conjunto de arquivos
relacionados entre si com registros. Eles são coleções de dados que se
relacionam para atribuir algum sentido e/ou eficiência durante ao seu serviço.
 
Os bancos de dados atualmente são divididos em relacional (Mysql, Sql
Server, SQLite, etc …) e banco de dados não relacional (MongoDB,
DynamoDB, ArangoDB, Oracle NoSQL, etc …).
 
Vamos abordar apenas o uso de banco de dados relacional, e principalmente
o SQLite, porém você pode utilizar o banco de sua preferência. Além disso
vamos utilizar uma biblioteca para abstrair ao máximo o uso do banco de
dados, vamos utilizar o Dataset.
 
Não vou entrar em detalhes a respeito das operações de banco de dados,
espero que você tenha algum conhecimento a respeito, caso não tenha
procure algum material de apoio para os principais recursos de um banco de
dados. Porém você não terá dificuldades de acompanhar esse projeto, pois
utilizamos uma linguagem simplificada que facilitará seu aprendizado.
 
Basicamente todo banco de dados relacional tem os seguintes aspectos:
 
Nome do banco: É o nome dado ao banco, todo banco de dados tem
várias tabelas;
Tabelas: Uma tabela é composta por linhas e colunas, assim como no
Excel;
Colunas: As colunas representa uma chave fixa, ou seja, ela é
predefinida no início da tabela ou é adicionada posteriormente quando
há necessidade;
Linhas: São os dados em si, quando construímos um banco o que
queremos extrair deles é exatamente as linhas.
 
 
Como de costume vamos criar um novo projeto para reforçar nosso
aprendizado:
 
md ProjetoBanco
cd ProjetoBanco
. > __init__.py
. > app.py
C:\Python27\Scripts\virtualenv.exe pjdb_env
pjdb_env\Scripts\activate
 
E instale o Flask e o Dataset
pip install Flask
pip install dataset
 
15.1. Criando uma conexão SQLite
 
Para se conectar a um banco de dados, você precisa identificá-lo por sua
URL, que basicamente é uma string no formato
"dialect://user:password@host/dbname". Aqui estão alguns exemplos para
diferentes tipos de banco de dados:
 
# conexão usando o banco SQLite
db = dataset.connect('sqlite:///mydatabase.db')
 
# conexão usando o banco MySQL passando o usuário e senha
db = dataset.connect('mysql://user:password@localhost/mydatabase')
 
No nosso caso vamos utilizar a conexão do sqlite e para isso precisamos
ajustar nosso projeto.
 
Abra o arquivo app.py e escreva:
 
1. # coding: utf-8
2. from flask import Flask
3. import dataset
4.
5. app = Flask(__name__)
6. db = dataset.connect('sqlite:///primeirobanco.db')
7.
8. @app.route('/')
9. def index():
10. return "Olá SQLite!", 200
11.
12. app.run()
 
Linha 3: Vamos importar o dataset, para podermos manipular as informações
do banco de maneira simplifica.
Linha 6: Criamos uma variável chamada db, ou data base, usando uma
conexão SQLite. Note que nomeamos o banco de dados de
primeirobanco.db e esse arquivo pode ser acessado na raiz do seu projeto.
 
 
15.2. Criando uma Tabela
 
Para armazenar dados, você precisa ter como referência uma tabela. Usando o
dataset você não precisa se preocupar se a tabela já existe ou não, pois ele
fará esse trabalho para nós, vamos alterar o nosso arquivo app.py e fazer os
ajustes necessários:
 
…
8. @app.route('/')
9. def index():
10. pessoa = db['pessoa']
11. return "Olá SQLite!", 200
…
Linha 10: Vamos criar uma variável que representará nossa tabela e
iniciamos ela usando nossa conexão com o banco de dados db['pessoa']
passando como parâmetro o nome da tabela que queremos manipular.
 
15.3. Inserindo dados
 
Com nossa tabela construída precisamos criar inserir dados nela, para isso
vamos utilizar a função insert. Além disso como estamos utilizando o
dataset você não vai precisar criar os dados das colunas, pois ele fará isso
automaticamente:
 
…
8. @app.route('/')
9. def index():
10. pessoa = db['pessoa']
11. pessoa.insert(dict(nome="Wallace", idade=30))
12. return "Olá SQLite!", 200
…
 
Linha 11: Utilizando nossa variável da tabela, vamos usar a função insert e
passar como parâmetro um dicionário com a chave (representando nossa
coluna) e o valor (representando o dado para a linha)
 
Ao executar esse projeto vamos notar que nada vai mudar, não será
apresentada nenhuma informação, porém os dados foram inseridos.
 
Para podermos manipular melhor as informações, vamos adicionar outras
informações:
 
pessoa.insert(dict(nome="Vanessa", idade=45))
pessoa.insert(dict(nome="Paula", idade=21))
pessoa.insert(dict(nome="Arthur", idade=18))
pessoa.insert(dict(nome="Miguel", idade=31))
 
15.4. Listando dados
 
Para listar os dados e apresentá-los a nossa página precisamos entender 3
formas que o dataset oferece ao fazer a listagem:
 
Listar tudo
 
Para listar todas as informações da tabela, vamos utilizar a função all.
…
24. @app.route('/listar_tudo/')
25. def listartudo():
26. lista = db['pessoa'].all()
27. html = u"Listando tudo!<br>"
28.
29. for linha in lista:
30. html = html + str(linha['id']) + u" - Nome: " + linha['nome'] +
u" - Idade: " + str(linha['idade']) + u"<br>"
31. return html, 200
…
 
Linha 26: Vamos criar uma variável chamado lista para armazenar o retorno
de todos os dados do nosso banco, e em seguida vamos usar a função all para
listar os dados da tabela pessoa.
Linha 29: Vamos percorrer a lista utilizando o laço de repetição for, e
armazenar cada linha que retornar na variável linha.
Linha 30: Em seguida vamos adicionar cada informação que foi retornada na
linha ao nosso html, lembre-se de sempre colocar como parâmetro apenas as
informações da coluna, no nosso caso utilizei as colunas id (criado
automaticamente), nome eidade.
 
Execute o projeto e veja os resultados obtidos, acessando a URL
http://127.0.0.1:5000/listar_tudo/.
 
Listar uma linha
 
Para listar apenas uma linha da nossa tabela, vamos utilizar a função
find_one.
 
…
33. @app.route('/listar_um/')
34. def listarum():
35. linha = db['pessoa'].find_one(nome="Wallace")
36. html = u"Listando um!<br>"
37. html = html + str(linha['id']) + u" - Nome: " + linha['nome'] + u" -
Idade: " + str(linha['idade']) + u"<br>"
http://127.0.0.1:5000/listar_tudo/
38. return html, 200
…
 
Linha 35: Vamos recuperar apenas uma linha da nossa tabela, usando a
função find_one, passando como parâmetro o nome da coluna e a informação
que procuramos.
Linha 37: Com a informação da linha recuperada, podemos agora acessar as
informações dela e passar para nosso html.
 
Execute o projeto e veja os resultados obtidos, acessando a URL
http://127.0.0.1:5000/listar_um/.
 
Listar com filtros
 
E por fim, podemos fazer uma busca em nossa tabela utilizando filtros
específicos, para isso vamos usar a função find.
 
Podemos ordenar nossa tabela:
 db['pessoa'].find(order_by='nome')
 
Podemos também listar apenas algumas linhas:
 db['pessoa'].find(_limit=2)
 
Ou até carregar a partir de algum registro específico:
 db['pessoa'].find(_offset=2)
 
Caso seja necessário podemos utilizar a função query para fazer qualquer tipo
de consulta no banco, utilizando qualquer operação do banco selecionado:
db.query('SELECT * FROM pessoa')
 
Vejamos como fica:
…
40. @app.route('/listar_com_filtros/')
41. def listarcomfiltros():
42. lista = db['pessoa'].find(_limit=2, order_by='nome', _offset=2)
43. html = u"Listando com filtros!<br>"
44.
http://127.0.0.1:5000/listar_um/
45. for linha in lista:
46. html = html + str(linha['id']) + u" - Nome: " + linha['nome'] + u" -
Idade: " + str(linha['idade']) + u"<br>"
47. return html, 200
…
 
Linha 42: Filtrando a tabela pessoa, limitando por 2 linhas, a partir da
segunda linha e ordenado pela coluna nome.
 
15.5. Atualizando dados
 
Para atualizar os dados da tabela, vamos utilizar a função update, passando
como primeiro parâmetro um dicionário com os dados que queremos alterar e
o segundo parâmetro um filtro, como por exemplo o id do registro que
queremos alterar.
 
…
50. @app.route('/atualizar/')
51. def atualizar():
52. db['pessoa'].update(dict(id=1,idade=40), ['id'])
53. return u"Alterando a idade da pessoa <b>Wallace</b> para 40.", 200
…
 
Linha 52: Usando a tabela pessoa e a função update para alterar o dicionário
que passamos, sendo que o que realmente vai ser alterado é a idade do
registro 1.
 
 
15.6. Excluindo dados
 
Para excluir qualquer registro da tabela vamos utilizar a função delete:
 
…
55. @app.route('/excluir/')
56. def excluir():
57. db['pessoa'].delete(id=5)
58. return u"Excluindo o registro com id<b>5</b>.", 200
…
 
Linha 57: Excluindo o registro com o id 5.
 
Com essa última operação concluímos esse capítulo e com tudo que
aprendemos até aqui, já podemos criar um sistema!
 
16. O que é um Blueprint
 
Blueprints são projetos Flask separados em arquivos e que podem ter
funcionalidades complementares e únicas. Cada Blueprint pode ser usados
em camadas e isso te ajuda a organizar melhor o seu projeto.
 
Para exemplificar vamos criar um novo projeto:
 
md ProjetoBlueprint
cd ProjetoBlueprint
. > __init__.py
. > app.py
C:\Python27\Scripts\virtualenv.exe pjbp_env
pjbp_env\Scripts\activate
 
E instale o Flask:
pip install Flask
 
Para entender como funcionará o nosso projetos, vamos imaginar que neste
projeto tenhamos 2 funcionalidades que podem ser usadas em qualquer
projeto, como por exemplo transformar nossos dados em uma API e outro
exemplo e a conversão de Arquivos.
 
Para não poluir nosso arquivo principal vamos criar 2 Blueprints e um outro
para carregar as informações da tela inicial.
 
Nosso projeto deve ficar assim:
 
ProjetoBlueprint/
__init__.py
app.py
pjbp_env/
blueprints/
__init__.py
index.py
api.py
converter.py
 
Portanto vamos ajustar nosso arquivo app.py:
 
1. # coding: utf-8
2. from flask import Flask
3. from blueprints.index import bp_index
4. from blueprints.api import bp_api
5. from blueprints.converter import bp_converter
6.
7. app = Flask(__name__)
8. app.register_blueprint(bp_index)
9. app.register_blueprint(bp_api)
10. app.register_blueprint(bp_converter)
11.
12. app.run()
 
Linha 3, 4 e 5: Faz a importação dos arquivos que usaremos nesse aplicativo,
e carrega a variável do Blueprint de cada arquivo.
Linha 8, 9 e 10: Registra cada Blueprint importado ao nosso aplicativo
principal.
 
Vamos dar uma olhada em cada arquivo:
 
blueprints/index.py:
 
1. # coding: utf-8
2. from flask import Blueprint
3.
4. bp_index = Blueprint('index', __name__)
5.
6. @bp_index.route('/')
7. def index():
8. return u"Olá Projeto Blueprint!", 200
 
blueprints/api.py:
 
1. # coding: utf-8
2. from flask import Blueprint
3.
4. bp_api = Blueprint('api', __name__)
5.
6. @bp_api.route('/api/')
7. def api():
8. return u"Olá Você está na página da API!", 200
 
blueprints/converter.py:
 
1. # coding: utf-8
2. from flask import Blueprint
3.
4. bp_converter = Blueprint('converter', __name__)
5.
6. @bp_converter.route('/converter/')
7. def converter():
8. return u"Olá Você está na página da CONVERTER!", 200
Vamos ver o que eles tem em comum:
 
Linha 4: Cria o Blueprint e ajusta o nome para facilitar a identificação.
Linha 6: Adiciona a rota de acordo com o nome dado ao Blueprint.
 
Note que basicamente todos são iguais, porém cada um registra a rota de
forma separada, e pode ser acessado de acordo com elas, vamos executar
nosso projeto.
 
No seu terminal com o pjbp_env ativo, execute o comando: python app.py
 
Agora vamos acessar todas as rotas cadastradas no projeto e ver o resultado:
 
http://127.0.0.1:5000/ ← Acessa o Blueprint index.py
http://127.0.0.1:5000/api ← Acessa o Blueprint api.py
http://127.0.0.1:5000/converter/ ← Acessa o Blueprint converter.py
 
 
http://127.0.0.1:5000/
http://127.0.0.1:5000/api
http://127.0.0.1:5000/converter/
Com esse recurso podemos gerenciar melhores nossos projetos e separar os
arquivos de acordo com nossa necessidade, sem ter que nos preocupar de
ficar gerenciando em uma infinidade de ações em um único arquivo.
 
Com isso finalizamos todos os conceitos básico desse framework, agora
vamos pôr em prática tudo o que aprendemos em um projeto!
17. Projeto WebApp – Pizzaria
 
Vamos criar um site com sistema para uma Pizzaria qualquer, como todos
nós já deve ter tido algum contato com algum site, ou até mesmo a falta de
um, de alguma pizzaria de bairro.
 
Para isso vamos explorar algumas das principais características desses
refinados estabelecimentos, começando do acesso à lista de Pizza até a
entrega do pedido ao cliente.
 
Vamos estabelecer os seguintes REQUISITOS:
 
O site deve apresentar TODAS as Pizzas disponíveis;
Essas Pizzas são cadastradas pelo pelo Gerente;
O Cliente só PODE realizar os pedidos, caso estejam cadastrados e
logados no sistema;
O Cliente DEVE realizar seu cadastro de maneira simplificada,
informando seu Nome, E-mail, Senha;
O Gerente deve informar os status (Recebido, Enviar para o cliente,
etc) do pedido do Cliente;
O Gerente não pode ter acesso aos dados dos Clientes;
 
Essa é a ideia principal do nosso projeto e agora podemos começar a separar
as atividades de cada ATOR, atribuindo suas responsabilidades e restrições.
Porém não vou entrar a fundo na construção de modelos UML ou
mapeamento de banco de dados, pois não é o objetivo deste livro.
 
Vamos criar nosso projeto final:
md ProjetoPizzaria
cd ProjetoPizzaria
. > __init__.py
. > app.py
C:\Python27\Scripts\virtualenv.exe pjfinal_env
pjfinal_env\Scripts\activate
 
E instale o Flask:
pip install Flask
pip install dataset
 
Agora vamos organizar nossa estrutura de pastas:
 
 
ProjetoPizzaria_v1/
__init__.py
app.py
pjfinal_env/
controller/
__init__.py
site.py
templates/
site/
index.html
static/
css/
folha.css
js/
img/
pizza.jpg
util/
 
A medida que formos construindo o projeto, vamos preenchendo as
informações com os arquivose/ou com novas estruturas.
 
A pasta static é destinada aos arquivos que desejamos carregar dentro das
nossas páginas em html, e carregá-los utilizando a função url_for.
 
Nesse nosso projeto vamos utilizar essa pasta para os arquivos de css,
javascript e as imagens que pretendemos carregar.
 
Podemos acompanhar essa configuração na pasta ProjetoPizzaria_v1.
 
A pasta pjfinal_env foi removida devido o seu tamanho, se sempre que for
testar o projeto, lembre-se de adicioná-la à raiz do projeto para que tudo
funcione corretamente.
 
17.1. Criando a página principal
 
Na página principal vamos criar uma tela simples com as informações que
qualquer um pode consultar, com os preços e as pizzas. Para você não se
perder, vamos fazer a criação aos poucos, tela a tela e com suas
características inicial e em seguida com seus ajustes.
 
Ao executarmos o ProjetoPizzaria_v1, podemos destacar alguns pontos
importantes:
 
No arquivo app.py:
 
1. # coding: utf-8
2. from flask import Flask
3. from controller.site import bp_site
4.
5. app = Flask(__name__)
6. app.register_blueprint(bp_site)
7.
8. app.run()
 
Linha 3: Vamos separar cada propriedade em vários Blueprints, para termos
controle absoluto e melhorar a organização do nosso projeto.
Linha 6: Não se esqueça de registrar o Blueprint sempre que importar.
 
No arquivo templates/site/index.html:
 
1. <html>
2. <head>
3. <title>Pizzaria - Projeto Final</title>
4. <link rel="stylesheet" href="{{ url_for('static',
filename='css/folha.css') }}">
5. </head>
6. <body>
…
 
Linha 4: Estamos carregando a folha de estilo do css através da pasta static.
 
Como o objetivo é aprender sobre o framework Flask, não vamos dedicar
tempo discutindo o que foi feito no css, ou até mesmo na forma que o site da
Pizzaria foi feito. Fique à vontade para fazer seus ajustes, porém nesse
momento sugiro que dê mais atenção em como o projeto está sendo feito, do
que no design em si.
 
Uma das primeiras coisas que precisamos fazer antes de criar a área dos
clientes, é ter o acesso aos usuários, e para isso precisamos criar a tela de
login.
 
17.2. Criando área de acesso para Clientes
 
Vamos criar um Blueprint bp_usuario, e ter a possibilidade de fazer login,
sair do sistema e alterar seus dados, e por isso precisamo criar também o
gerenciamento da sessão, vamos lá.
 
Para você ter uma ideia das alterações que foram feitas, eu criei outro projeto
chamado ProjetoPizzaria_v2 e nele você pode ver as alterações necessárias
para a construção do gerenciamento de usuários.
 
ProjetoPizzaria_v2/
__init__.py
app.py
pjfinal_env/
controller/
__init__.py
site.py
usuario.py
templates/
site/
usuario/
login.html
registro.html
erro_cadastro.html
sucesso_cadastro.html
static/
util/
banco.py
 
No arquivo app.py:
 
1. # coding: utf-8
2. from flask import Flask, session
3. from controller.site import bp_site
4. from controller.usuario import bp_usuario
5.
6. app = Flask(__name__)
7. app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'
8.
9. app.register_blueprint(bp_site)
10. app.register_blueprint(bp_usuario)
11.
12. app.run()
 
Linha 4: Estou importando o Blueprint de usuario.
Linha 7: Estou adicionando uma chave para o gerenciamento das sessões.
Linha 10: Estou registrando o Blueprint de usuario para o nosso aplicativo
principal.
 
No arquivo util/banco.py:
 
1. # coding: utf-8
2. import dataset
3.
4. class Banco:
5. def saveUsuario(self, nome, usuario, senha):
6. with dataset.connect('sqlite:///pizzaria.db') as db:
7. if ( self.getUsuario(usuario, senha) ):
8. return False
9. else:
10 return db['usuario'].insert(dict(nome=nome, usuario=usuario,
senha=senha))
11.
12. def getUsuario(self, usuario, senha):
13. with dataset.connect('sqlite:///pizzaria.db') as db:
14. usuario = db['usuario'].find_one(usuario=usuario, senha=senha)
15.
16. if usuario:
17. return usuario
18. else:
19. return False
 
Esse arquivo é destinado ao gerenciamento de todas as funções que serão
relacionadas ao banco de dados, e por isso vamos começar criando alguns
métodos.
 
Linha 2: Faz a importação do nosso conector que usaremos para gerenciar as
requisições ao banco SQLite.
Linha 5: Esse método serve para adicionar novos usuários ao nosso sistema;
Linha 12: Esse método serve para verificar se os usuários já estão cadastrado
no sistema;
 
No arquivo controller/usuario.py:
 
1. # coding: utf-8
2. from flask import Blueprint, render_template, session, request,
redirect, url_for
3. from util.banco import Banco
4.
5. bp_usuario = Blueprint('usuario', __name__)
6. banco = Banco()
…
 
Linha 2: Vamos fazer a importação de todos os recursos do framework que
vamos precisar usar.
Linha 3: Vamos importar o gerenciador de conexão.
Linha 5: Criaremos o Blueprint chamado usuario.
Linha 6: Vamos iniciar nossa classe e criar uma variável para usar nesse
Blueprint.
 
Vamos configurar a rota para acessar a área de Login através da URL
http://127.0.0.1:5000/usuario/login/
…
8. @bp_usuario.route('/usuario/login/')
9. def login():
10. return render_template("usuario/login.html"), 200
…
 
Essa área vai carregar as informações do formulário de login, para o usuário
acessar o sistema ou criar uma conta.
 
Como inicialmente você não deve ter nenhum usuário registrado, podemos
criá-lo através dessa função:
…
24. @bp_usuario.route('/usuario/registro/')
25. def registro():
26. return render_template("usuario/registro.html"), 200
…
 
Agora ao acessar o link do registro, podemos ver o formulário para cadastrar
nosso primeiro usuário, que será gerenciado através da função:
 
…
28. @bp_usuario.route('/usuario/cadastro/', methods=['GET','POST'])
29. def cadastro():
30. if request.method == "GET":
31. return render_template("usuario/erro_cadastro.html"), 200
32. elif request.method == "POST":
33. if ( banco.saveUsuario(request.form['nome'],
request.form['usuario'], request.form['senha']) ):
34. session['usuario'] = {"nome": request.form['nome'],
"usuario": request.form['usuario']}
35. return render_template("usuario/sucesso_cadastro.html"), 200
36. else:
37. return render_template("usuario/erro_cadastro.html"), 200
http://127.0.0.1:5000/usuario/login/
…
 
Linha 31: Se por acaso alguém tentar realizar o cadastro que não seja pelo
formulário, ele vai apresentar uma tela de Erro.
Linha 33 e 34: Se ele usar o formulário corretamente, vamos tentar salvar o
usuário, e se der tudo certo ele deve cadastrar no banco de dados e armazenar
na sessão o nome do usuário e seu login.
Linha 37: Caso ele informe um usuário invalido, ou tenha algum erro na
execução do cadastro, ele será levado para uma tela de erro de cadastro e
poderá tentar novamente.
 
Agora que já sabemos como cadastrar um usuário, vamos ver se esse usuário
existe e direcionar para a tela principal, carregando as informações dele na
sessão.
 
Ao acessar a URL http://127.0.0.1:5000/usuario/login/ você poderá digitar
seu usuário e senha que você criou, se ele existir, então vamos logar no
sistema, se não vamos apresentar uma mensagem de erro informando que o
usuário não existe ou é invalido!
…
12. @bp_usuario.route('/usuario/autenticar/', methods=['GET','POST'])
13. def autenticar():
14. if request.method == "GET":
15. return render_template("usuario/login.html", erro=u"Não foi
possível realizar o login!"), 200
16. elif request.method == "POST":
17. usuario = banco.getUsuario(request.form['usuario'],
request.form['senha'])
18. if ( usuario ):
19. session['usuario'] = {"nome": usuario['nome'], "usuario":
usuario['usuario']}
20. return redirect(url_for('site.site'))
21. else:
22. return render_template("usuario/login.html", erro=u"Usuário ou
Senha inválidos!"), 200
…
 
http://127.0.0.1:5000/usuario/login/
Linha 15: Se ele tentar logar sem usar o formulário, ele vai apresentar a
mensagem de erro “Não foi possível realizar o login!”.
Linha 17, 18, 19 e 20: Se ele fizer o login através do formulário, ele vai
verificar se o usuário existe acessando o banco de dados (banco.getUsuario),
se ele identificar que o usuário corresponde ao usuário que está no banco de
dados, então ele vai deixar o usuário ir para atela principal, se não ele vai
redirecionar para a tela de login com a mensagem “Usuário ou senha
inválidos!”.
 
Agora que já podemos criar um usuário, e fizemos o login do usuário,
precisamos sair do nosso usuário.
 
…
39. @bp_usuario.route('/usuario/sair/')
40. def sair():
41. session.pop('usuario', None)
42. return redirect(url_for('site.site'))
…
 
Neste caso não precisamos verificar a existência de nenhum formulário, ele
pode sair do sistema da forma que preferir, seja clicando no botão de sair na
tela principal ou apenas digitando a URL http://127.0.0.1:5000/usuario/sair/
em seu navegador, que assim que acessar, ele será redirecionado para a tela
principal sem utilizar o seu usuário.
 
E com isso finalizamos a segunda parte do projeto, que é destinada ao
gerenciamento de usuários.
 
Agora que podemos gerenciar os usuários, precisamos identificar o tipo, para
os clientes vamos criar no banco de dados a informação tipo, e para o público
em geral vamos identificá-lo como usuário.
 
Separei esses ajustes no ProjetoPizzaria_v3.
 
No arquivo templates/usuario/registro.html:
 
…
http://127.0.0.1:5000/usuario/sair/
84. <form action="{{ url_for('usuario.cadastro') }}" method="post">
85. <div class="container">
86. <input type="hidden" name="tipo" value="usuario"/>
87. <label for="nome"><b>Nome</b></label>
88. <input type="text" placeholder="Digite seu Nome" name="nome"
required>
89.
90. <label for="usuario"><b>Usuário</b></label>
91. <input type="text" placeholder="Digite seu Usuário" name="usuario"
required>
92.
93. <label for="senha"><b>Senha</b></label>
94. <input type="password" placeholder="Digite sua Senha" name="senha"
required>
95. 
96. <button type="submit">Cadastrar</button>
97. <br>
98. <button type="button" class="cancelbtn" onclick="window.location =
'{{ url_for('site.site') }}';">Cancelar</button>
99. </div>
100.
101. </form>
…
 
Linha 86: Adicionamos o campo no formulário para identificar o tipo, que
nesse caso será usuário.
 
Precisamos modificar também ao realizar o cadastro do usuário, então vamos
alterar o arquivo controlle/usuario.py:
 
…
28. @bp_usuario.route('/usuario/cadastro/', methods=['GET','POST'])
29. def cadastro():
30. if request.method == "GET":
31. return render_template("usuario/erro_cadastro.html"), 200
32. elif request.method == "POST":
33. if ( banco.saveUsuario(request.form['nome'],
request.form['usuario'], request.form['senha'], request.form['tipo']) ):
34. session['usuario'] = {"nome": request.form['nome'],
"usuario": request.form['usuario'], "tipo": request.form['tipo']}
35. return render_template("usuario/sucesso_cadastro.html"), 200
36. else:
37. return render_template("usuario/erro_cadastro.html"), 200
…
 
Linha 33: Agora devemos passar o tipo que recebemos do formulário para o
nosso método do banco de dados banco.saveUsuario().
Linha 34: Em seguida, se ele for cadastrado, então adicione também na
sessão do sistema.
 
E também vamos alterar ao acessar o sistema:
 
…
12. @bp_usuario.route('/usuario/autenticar/', methods=['GET','POST'])
13. def autenticar():
14. if request.method == "GET":
15. return render_template("usuario/login.html", erro=u"Não foi
possível realizar o login!"), 200
16. elif request.method == "POST":
17. usuario = banco.getUsuario(request.form['usuario'],
request.form['senha'])
18. if ( usuario ):
19. session['usuario'] = {"nome": usuario['nome'], "usuario":
usuario['usuario'], "tipo": usuario['tipo']}
20. return redirect(url_for('site.site'))
21. else:
22. return render_template("usuario/login.html", erro=u"Usuário ou
Senha inválidos!"), 200
…
 
Linha 19: Recuperar o tipo do usuário e em seguida adicionar na sessão.
 
Por fim vamos alterar o método banco.saveUsuario() para receber o
parâmetro tipo e inserir no banco de dados, alterando o arquivo
util/banco.py:
 
 
…
5. def saveUsuario(self, nome, usuario, senha, tipo):
6. with dataset.connect('sqlite:///pizzaria.db') as db:
7. if ( self.getUsuario(usuario, senha) ):
8. return False
9. else:
10. return db['usuario'].insert(dict(nome=nome, usuario=usuario,
senha=senha, tipo=tipo))
…
 
Linha 5 e 10: Vamos acrescentar o tipo como parâmetro e inseri-lo no banco.
 
 
17.3. Criando área de acesso para Gerentes
 
Da mesma forma que criamos com o usuário, vamos criar uma Blueprint para
gerentes, dar acesso ao sistema e ter uma área para cadastrá-los.
 
No ProjetoPizzaria_v3 vamos adicionar os seguintes arquivos:
 
ProjetoPizzaria_v3/
__init__.py
app.py
pjfinal_env/
controller/
__init__.py
site.py
usuario.py
gerencia.py
templates/
site/
usuario/
gerente/
registro.html
static/
util/
 
 
Inicialmente vamos ter uma área de cadastro de gerentes, porém ele não deve
ser listado em nenhuma área visível, pois no futuro apenas o Admin poderá
criá-lo.
 
No arquivo controller/gerencia.py:
 
1. # coding: utf-8
2. from flask import Blueprint, render_template, session, request, redirect,
url_for
3. from util.banco import Banco
4.
5. bp_gerencia = Blueprint('gerencia', __name__, url_prefix='/gerencia')
6. banco = Banco()
7.
8. @bp_gerencia.route('/registro/')
9. def gerencia_registro():
10. return render_template("gerencia/registro.html"), 200
 
Linha 5: Podem perceber que dessa vez, optei por adicionar no construtor do
nosso Blueprint uma URL pré-fixada, permitindo assim que o framework
entenda que das as rotas desse Blueprint será realizada através do termo
gerencia.
 
E por fim, no arquivo de templates/gerencia/registro.html, apenas substitui
na linha 86 o tipo de usuario para gerente.
 
17.4. Criando área para cadastro de Pizzas
 
Na área de cadastro de Pizzas, só devemos permitir que o usuário do tipo
gerente possa acessá-lo, e por isso vamos criar um novo Blueprint para esse
tipo de atividade.
 
No ProjetoPizzaria_v4 vamos adicionar os seguintes arquivos:
 
ProjetoPizzaria_v4/
__init__.py
app.py
pjfinal_env/
controller/
__init__.py
site.py
usuario.py
gerencia.py
pizzas.py
templates/
site/
usuario/
gerente/
pizzas/
cadastro.html
lista.html
static/
util/
 
Primeiro vamo ver as alterações no arquivo util/banco.py:
 
21. def listPizzas (self):
22. with dataset.connect('sqlite:///pizzaria.db') as db:
23. pizzas = db['pizzas'].all()
24. return pizzas
25.
26. def getPizza (self, id):
27. with dataset.connect('sqlite:///pizzaria.db') as db:
28. pizza = db['pizzas'].find_one(id=id)
29.
30. if pizza:
31. return pizza
32. else:
33. return False
34.
35. def savePizza(self, nome, descricao):
36. with dataset.connect('sqlite:///pizzaria.db') as db:
37. return db['pizzas'].insert(dict(nome=nome, descricao=descricao,
status='ativo')) 
38.
39. def updatePizza(self, id, nome, descricao, status):
40. with dataset.connect('sqlite:///pizzaria.db') as db:
41. return db['pizzas'].update(dict(id=id, nome=nome,
descricao=descricao, status=status), ['id']) 
42.
43. def deletePizza(self, id):
44. with dataset.connect('sqlite:///pizzaria.db') as db:
45. return db['pizzas'].delete( id=id )
 
Linha 21: Vamos criar um método para listar todas as pizzas.
Linha 26: Neste método vamos recuperar apenas um registro da tabela
pizzas., passando como parâmetro o id da pizza.
Linha 35: Aqui vamos passar os dados para salvar no banco as informações
das pizzas, como o seu nome e sua descrição.
Linha 39: Neste método podemos fazer alterações nas informações da pizza,
sem alterar o registro de pedidos.
Linha 43: E por fim, vamos remover do banco as pizzas que não queremos
mais em nosso catálogo.
 
Com isso, já podemos fazer todo o gerenciamento da tabela pizzas, e
podemos passar para a etapa de ajustes no Blueprint.
 
Agora é hora de ver o arquivo controlle/pizzas.py:
 
…
8. @bp_pizzas.route('/lista/')
9. def lista():
10. lista = banco.listPizzas()
11. return render_template("pizzas/lista.html", lista=lista), 200
…
 
Neste primeiro método, vamos listar todas as pizzas cadastradas em nossa
lista do HTML, e caso não tenha nenhuma cadastrada, ele deve informar que
não existe nenhuma pizza e que pode ser adicionada.
 
Vejamos o arquivo templates/pizzas/lista.html:29. <div class="card">
30. {% if not lista %}
31. Nenhuma Pizza foi cadastrada, por favor cadastre uma agora
mesmo! <br>
32. <a href="{{ url_for('pizzas.cadastro') }}"> CADASTRA </a>
33. {% else %}
34. <table width="100%">
35. <thead>
36. <tr>
37. <th>Nome</th>
38. <th>Descrição</th>
39. <th>Ação</th>
40. </tr>
41. </thead>
42. <tbody>
43. {% for item in lista %}
44. <tr>
45. <td>{{ item['nome'] }}</td>
46. <td>{{ item['descricao'] }}</td>
47. <td>
48. <a href="{{ url_for('pizzas.cadastro') }}
{{item['id']}}">Alterar</a>
49. &nbsp;
50. <a onclick="return confirm('Deseja realmente excluir a Pizza
selecionada?')" href="{{ url_for('pizzas.excluir') }}
{{item['id']}}">Excluir</a>
51. </td>
52. </tr>
53. {% endfor %}
54. </tbody>
55. </table>
56. {% endif %}
57. </div>
 
Nos trechos destacados podemos ver a verificação da lista, caso não exista ele
apresenta a mensagem, e se existe e faz a interação dos dados e apresenta em
forma de tabela.
 
Vamos voltar ao arquivo controlle/pizzas.py:
…
13. @bp_pizzas.route('/cadastro/')
14. @bp_pizzas.route('/cadastro/<int:id>')
15. def cadastro( id = None ):
16. dados = {'id':'','nome':'','descricao':''}
17. if id :
18. dados = banco.getPizza( id )
19.
20. return render_template("pizzas/cadastro.html", pizza = dados), 200
…
 
Aqui vamos realizar o cadastro, note que vamos ajustar a rota para recuperar
o id através da URL, com isso podemos recuperar os dados para fazer
alterações.
 
Salvando os dados
…
22. @bp_pizzas.route('/salvar/', methods=['POST'])
23. def salvar():
24. if request.method == "POST":
25. if request.form['id'] and request.form['id'] != '' :
26. banco.updatePizza(request.form['id'], request.form['nome'],
request.form['descricao'], 'ativo')
27. else:
28. banco.savePizza(request.form['nome'], request.form['descricao'])
29. return redirect(url_for('pizzas.lista'))
…
 
Aqui vamos fazer a persistência dos dados, verificando se existe id, no caso
de existir podemos atualizar os dados, caso o contrário vamos criar um novo
registro.
 
Excluindo os registros
…
31. @bp_pizzas.route('/excluir/')
32. @bp_pizzas.route('/excluir/<int:id>')
33. def excluir( id = None ):
34. if id:
35. banco.deletePizza(id)
36. return redirect(url_for('pizzas.lista'))
…
 
Para finalizar a estrutura de gerenciamento, temos a possibilidade de excluir
aqueles registros que não queremos mais apresentar em nosso cardápio. Só
que diferente de cadastrar uma nova pizza ou alterá-la utilizando uma tela de
cadastro, vamos utilizar o javascript para fazer esse pedido, e por isso vamos
ajustar a rota para aceitar apenas no formato de excluir/id.
 
 
17.5. Criando área de Pedidos Clientes/Gerentes
 
Agora vamos finalizar o nosso projeto com o gerenciamento de pedidos, que
tem como objetivo receber os pedidos dos clientes, fazer a aprovação do
pedido e, por fim, fazer a entrega.
 
No ProjetoPizzaria_final vamos adicionar os seguintes arquivos:
 
ProjetoPizzaria_final/
__init__.py
app.py
pjfinal_env/
controller/
__init__.py
site.py
usuario.py
gerencia.py
pizzas.py
pedidos.py
templates/
site/
usuario/
gerente/
pizzas/
pedidos/
cadastro.html
lista.html
lista_clientes.html
static/
util/
 
Como de costume vamos criar um Blueprint destinado aos pedidos:
 
Agora é hora de ver o arquivo controlle/pedidos.py:
 
…
1. # coding: utf-8
2. from flask import Blueprint, render_template, session, request,
redirect, url_for
3. from util.banco import Banco
4.
5. bp_pedidos = Blueprint('pedidos', __name__, url_prefix='/pedidos')
6. banco = Banco()
…
 
Linha 1 e 2: Vamos fazer as importações de tudo que vamos precisar.
Linha 5: Vamos iniciar o Blueprint, e colocar o nome de pedidos usando
como prefixo da URL o /pedidos como padrão para todos os acessos da URL.
 
Vamos precisar também, criar uma rota para a lista de pedidos, para Clientes
ele deve apresentar todos os pedidos e o status do pedido dele:
 
…
8. @bp_pedidos.route('/lista/')
9. def lista():
10. if session['usuario']['tipo'] == 'gerente':
11. lista = banco.listPedidos()
12. return render_template("pedidos/lista.html", lista=lista,
banco=banco), 200
13. else:
14. lista = banco.listPedidosClientes(session['usuario']['id'])
15. return render_template("pedidos/lista_clientes.html", lista=lista,
banco=banco), 200
…
 
Linha 10: Se o usuário for do tipo gerente, deve apresentar a lista de pedidos
de todos os clientes.
Linha 14: A lista deve ser carregada de acordo com o id do cliente, que nesse
caso traz todas os pedidos que esse cliente realizou.
 
Para pedidos que os gerentes precisam lidar, vamos ver o arquivo
templates/pedidos/lista.html:
 
26. <div class="row">
27. <div class="card">
28. {% if lista == False %}
29. Nenhum pedido encontrado! <br>
30. <a href="{{ url_for('pedidos.cadastro') }}">Fazer pedido</a>
31. {% else %}
32. <h3 align="center">Meus pedidos</h3>
33. <table width="100%">
34. <thead>
35. <tr>
36. <th>Clientes</th>
37. <th>Pedidos</th>
38. <th>Valor pedido</th>
39. <th>Status pedido</th>
40. <th>Ação</th>
41. </tr>
42. </thead>
43. <tbody>
44. {% for item in lista %}
45. <tr>
46. <td>{{ banco.getUsuarioID(item['usuario'])['nome'] }}</td>
47. <td>{{ banco.getPizza(item['codigo_pizza'])['nome'] }} - {{
banco.getPizza(item['codigo_pizza'])['descricao'] }}</td>
48. <td>R$ {{ item['tamanho_valor'].replace('.',',') }}</td>
49. <td>{{ item['status'] }}</td>
50. <td>
51. {% if item['status'] == 'Pendente' %}
52. <a onclick="return confirm('Deseja realmente enviar o pedido
para a Cozinha?')" href="{{ url_for('pedidos.status') }}{{item['id']}}/1">
53. Enviar para cozinha
54. </a>
55. {% elif item['status'] == 'Pronto para envio' %}
56. <a onclick="return confirm('Deseja realmente o pedido para o
Cliente?')" href="{{ url_for('pedidos.status') }}{{item['id']}}/2">
57. Enviar para o cliente
58. </a>
59. {% elif item['status'] == 'Entregue' %}
60. <a onclick="return confirm('Deseja realmente concluir o
pedido?')" href="{{ url_for('pedidos.status') }}{{item['id']}}/3">
61. Concluir pedido
62. </a>
63. {% else %}
64. Entregue
65. {% endif %}
66.
67. </td>
68. </tr>
69. {% endfor %}
70. </tbody>
71. </table>
72. {% endif %}
73. </div>
74. </div>
 
Linha 28: Verifica se não existem pedidos cadastrados.
Linha 31: Se existir então mostre os dados.
Linha 44: Pega todos os dados da lista e cria um item para cada linha dentro
do for.
Linhas 46 e 47: Vamos pegar as informações do item, e passar como
parâmetro para uma função do banco para recuperar as informações do
cliente e da pizza.
Linhas 51, 55, 59 e 63: Verifica qual tipo de status o pedido está, e apresenta
uma ação de acordo com cada status.
 
Quando o gerente recebe o pedido, ele pode decidir fazer uma ação de acordo
com a lista abaixo:
 
Status: Pendente → Gerente pode enviar para a Cozinha;
Status: Pronto para Envio → Gerente pode enviar para o Cliente;
Status: Entregue → Gerente pode finalizar o processo.
 
Cada ação desse informa ao cliente o status do seu pedido.
 
O Cliente pode criar um pedido acessando essa ação:
…
17. @bp_pedidos.route('/cadastro/')
18. @bp_pedidos.route('/cadastro/<int:id>')
19. def cadastro( id = None ):
20. dados = {'id':'','nome':'','descricao':''}
21. pizzas = banco.listPizzas()
22. if id :
23. dados = banco.getPizza( id )
24.
25. return render_template("pedidos/cadastro.html", pedido=dados,
pizzas=pizzas), 200
…
 
Linha 21: Lista as pizzas disponíveis para o pedido do cliente.
Linha 23: Se o cliente fizer algum pedido e decidir mudá-lo temos que listar
as informações do pedido.
 
Você pode ver a tela de pedidos no arquivo
templates/pedidos/cadastro.html.
 
Ao selecionar o pedido o cliente pode realizar o cadastro:
 
…
27. @bp_pedidos.route('/salvar/', methods=['POST'])
def salvar():
28. if request.method == "POST":
29. if request.form['id'] and request.form['id'] != '' :
30. banco.updatePedido(request.form['id'], request.form['pizza'],
request.form['preco'], request.form['usuario'])
31. else:
32. banco.savePedido(request.form['pizza'], request.form['preco'],
request.form['usuario'])
33. return redirect(url_for('pedidos.lista'))
…
 
Se o cliente desejarcancelar o pedido podemos fazê-lo através dessa função:
…
35. @bp_pedidos.route('/excluir/')
36. @bp_pedidos.route('/excluir/<int:id>')
37. def excluir( id = None ):
38. if id:
39. banco.deletePedido(id)
40. return redirect(url_for('pedidos.lista'))
…
 
E por fim podemos mudar o status de cada pedido pelo gerente:
…
42. @bp_pedidos.route('/status/')
43. @bp_pedidos.route('/status/<int:id>')
44. @bp_pedidos.route('/status/<int:id>/<int:status>')
45. def status( id = None, status = None):
46. if status == 1:
47. banco.statusPedido(id, status)
48. elif status == 2:
49. banco.statusPedido(id, status)
50. elif status == 3:
51. banco.statusPedido(id, status)
52. return redirect(url_for('pedidos.lista'))
…
 
Agora vamos ver esses novos métodos criados no arquivo util/banco.py:
 
Método destinado a recuperação dos dados do usuário pelo id dele:
…
21. def getUsuarioID(self, id):
22. with dataset.connect('sqlite:///pizzaria.db') as db:
23. usuario = db['usuario'].find_one(id=id)
24.
25. if usuario:
26. return usuario
27. else:
28. return False
…
 
Método destinado a recuperação da lista de pizzas:
…
30. def listPizzas (self):
31. with dataset.connect('sqlite:///pizzaria.db') as db:
32. pizzas = db['pizzas'].all()
33. if db['pizzas'].count() > 0 :
34. return pizzas
35. else:
36. return False
…
 
Método destinado a recuperação dos dados de uma pizza:
…
38. def getPizza (self, id):
39. with dataset.connect('sqlite:///pizzaria.db') as db:
40. pizza = db['pizzas'].find_one(id=id)
41.
42. if pizza:
43. return pizza
44. else:
45. return False
…
 
Método usado para gravar os dados de uma pizza:
…
47. def savePizza(self, nome, descricao):
48. with dataset.connect('sqlite:///pizzaria.db') as db:
49. return db['pizzas'].insert(dict(nome=nome, descricao=descricao,
status='ativo')) 
…
 
Método usado para atualizar a pizza:
…
51. def updatePizza(self, id, nome, descricao, status):
52. with dataset.connect('sqlite:///pizzaria.db') as db:
53. return db['pizzas'].update(dict(id=id, nome=nome,
descricao=descricao, status=status), ['id']) 
…
 
Método usado para excluir a pizza do banco de dados:
…
55. def deletePizza(self, id):
56. with dataset.connect('sqlite:///pizzaria.db') as db:
57. return db['pizzas'].delete( id=id )
…
 
Método destinado a listar todos os pedidos:
…
59. def listPedidos (self):
60. with dataset.connect('sqlite:///pizzaria.db') as db:
61. pedidos = db['pedidos'].all()
62.
63. if db['pedidos'].count() > 0 :
64. return pedidos
65. else:
66. return False
…
 
Método destinado a listar apenas os pedidos de um cliente:
…
68. def listPedidosClientes (self, id):
69. with dataset.connect('sqlite:///pizzaria.db') as db:
70. pedidos = db['pedidos'].find(usuario=id)
71.
72. if db['pedidos'].count(usuario=id) > 0 :
73. return pedidos
74. else:
75. return False
…
 
Método destinado a recuperação de um pedido:
…
77. def getPedido (self, id):
78. with dataset.connect('sqlite:///pizzaria.db') as db:
79. pedidos = db['pedidos'].find_one(id=id)
80.
81. if pedidos:
82. return pedidos
83. else:
84. return False
…
 
Método usado para gravar o pedido no banco:
…
86. def savePedido(self, pizza, preco, usuario):
87. with dataset.connect('sqlite:///pizzaria.db') as db:
88. return db['pedidos'].insert(dict(usuario=usuario,
codigo_pizza=pizza, tamanho_valor=preco, status='Pendente')) 
…
 
Método usado para atualizar o pedido:
…
90. def updatePedido(self, id, pizza, preco, usuario):
91. with dataset.connect('sqlite:///pizzaria.db') as db:
92. return db['pedidos'].update(dict(id=id, usuario=usuario,
codigo_pizza=pizza, tamanho_valor=preco), ['id']) 
…
 
Método usado para remover o pedido do banco:
…
94. def deletePedido(self, id):
95. with dataset.connect('sqlite:///pizzaria.db') as db:
96. return db['pedidos'].delete( id=id )
…
 
Método usado para alterar o status do pedido:
…
98. def statusPedido(self, id, status):
99. with dataset.connect('sqlite:///pizzaria.db') as db:
100. if status == 1:
101. return db['pedidos'].update(dict(id=id, status='Pronto para envio'),
['id'])
102. elif status == 2:
103. return db['pedidos'].update(dict(id=id, status='Entregue'), ['id'])
104. elif status == 3:
105. return db['pedidos'].update(dict(id=id, status='Concluido'), ['id'])
…
 
Método usado para recuperar a descrição do pedido:
107. def getValorPedidoDescricao(self, valor):
108. if valor == '11.90':
109. return u'Broto - R$ 11,90 - 4 Fatias'
110. elif valor == '21.90':
111. return u'Pequena - R$ 21,90 - 6 Fatias'
112. elif valor == '31.90':
113. return u'Média - R$ 31,90 - 8 Fatias'
114. elif valor == '41.90':
115. return u'Grande - R$ 41,90 - 10 Fatias'
116. elif valor == '51.90':
117. return u'Extra Grande - R$ 51,90 - 12 Fatias'
…
 
Agora que vimos por completo passo a passo como construir nosso sistema
para uma pizzaria, recomendo você a testá-lo em seu computador, se possível
não apenas teste, mais também tente fazer todo o código baseado neste livro,
se possível aprenda e crie um projeto com suas ideias, pois assim você vai
aprender muito mais rápido!
18. Próximos passos
 
Nesse ponto você já deve ter domínio de toda a estrutura e conceitos passado
nesse livro, e para expandir seu conhecimento sugiro que pratique o máximo
possível os exemplos e comece a criar pequenos projetos pessoais,
permitindo assim você compartilhar esse conhecimento e dúvidas com outras
pessoas. E pensando nas suas dúvidas, criei um Grupo fechado para
podermos compartilhar código, experiências e quem sabe até empregos.
 
Faça sua inscrição no Grupo Fechado do Facebook:
[Acessar]
 
 
19. Agradecimento
 
Obrigado por se interessar no conteúdo desse livro, espero que ele tenha
atendido sua expectativa sobre como funciona uma estrutura desse
framework e seus principais recursos, e que tenha aprendido ou ampliando
seus conhecimentos nessa área.
 
Espero ter facilitado sua caminhada e aproveito para deixar essa última dica,
não pare de aprender, pois o maior recurso do mundo é o conhecimento e
com ele podemos transformar todos ao nosso redor.
 
Um pedido especial
 
Se você gostou desse livro, eu gostaria de te pedir apenas mais um minuto do
seu tempo para ir na página desse livro no Site da Amazon e clicar no botão
“Escreva uma Avaliação” e deixar uma avaliação, pois isso vai me ajudar a
identificar os meus acertos e minhas falhas.
 
Peço também que me acompanhe no Facebook.
E me envie um e-mail (devacademybr@gmail.com) caso tenha alguma crítica
ou sugestão.
 
https://mailchi.mp/8aef57fc8a1d/grupo-fechado-livro
https://www.facebook.com/devacademybr
E por fim indique esse livro para um amigo, se você gostou, ele
provavelmente deve gostar!

Continue navegando