Baixe o app para aproveitar ainda mais
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. 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!
Compartilhar