from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello world'
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello world'
... mais o header...
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""Meu aplicativo web em Flask."""
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Hello world'
... mais a documentação do módulo...
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""Meu aplicativo web em Flask."""
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
"""Apresentação do 'root' do aplicativo."""
return 'Hello world'
... mais a documentação das funções...
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""Meu aplicativo web em Flask."""
from flask import Flask
from flask import render_template
app = Flask(__name__)
@app.route('/')
def index():
"""Apresentação do 'root' do aplicativo."""
return render_template('hello.html')
... mais retornar templates ao invés de texto puro...
#!/usr/bin/env python
# -*- encoding: utf-8 -*-
"""Meu aplicativo web em Flask."""
class Settings:
SECRET_KEY = 'Sup3rs3cr33t'
from flask import Flask
from flask import render_template
app = Flask(__name__)
app.config.from_object(Settings)
app.config.from_envvar('MEU_APLICATIVO_CONFIG')
@app.route('/')
def index():
"""Apresentação do 'root' do aplicativo."""
return render_template('hello.html')
... mais adicionar uma configuração...
... mais tratamento de erros...
... mais outras rotas...
... mais blueprints/applications...
... mais inicialização do ORM...
app = Flask(__name__)
__name__
é usado para que, internamente, os módulos/imports sejam encontrados.
Se o app estiver em "meuservico/app.py", as duas linhas abaixo funcionam de forma idêntica:
app = Flask(__name__)
app = Flask("meuservico")
Essa é a parte chata do Flask.
Existem dois contextos: Contexto de aplicação e Contexto que requisição.
Contexto de aplicação só existe quando o app está rodando.
Acessado com current_app
.
from flask import current_app
É a única forma de acessar dados da aplicação enquanto ela está rodando.
Contexto de requisição só existe quando o sistema está atendendo uma requisção (recebeu uma URL).
Acessado com request
.
from flask import request
Mais sobre request
mais adiante.
Para acessar as configurações, usa-se a propriedade config
da aplicação quando esta está rodando.
(Contexto de aplicação, lembra?)
from flask import current_app
from flask import render_template
@app.route('/')
def index():
return render_template('template.html',
order=current_app.config.get('ORDER_FIELD'))
Rotas são definidas com o decorator @[app].route([rota])
. Por exemplo:
app = Flask(__name__)
@app.route('/')
def index():
return 'Olá mundo'
Rotas também podem definir quais métodos HTTP são aceitos:
@app.route('/', methods=['POST', 'GET'])
def index():
return 'Olá mundo'
"PUT /
" irá retornar status 405: Method Not Allowed.
Rotas podem ser repetidas, desde que os métodos não colidam:
@app.route('/', methods=['GET'])
def list():
return 'Olá mundo'
@app.route('/', methods=['POST'])
def update():
return 'O seu mundo foi atualizado'
Rotas podem ter parâmetros:
app = Flask(__name__)
@app.route('/<usuario>/data')
def index(usuario):
return 'Olá {nome}'.format(nome=usuario)
Parâmetros podem ter um tipo definido:
@app.route('/add/<int:var1>/<int:var2>')
def add(var1, var2):
return 'Soma = {sum}'.format(sum=var1+var2)
Problemas: Número de rotas tente a crescer. E como passar app
para cima e para baixo?
Blueprints são funções relacionadas (por exemplo, pelo recurso base) que podem ser desenvolvidos separados do módulo principal e entre si.
(Conceito semelhante aos "apps" do Django ou "scaffolding" do Pyramid/Pylons.)
from flask import Blueprint
blueprint_exemplo = Blueprint('exemplo', __name__)
@blueprint_exemplo.route('/say/<usuario>')
def blueprint_index(usuario):
return 'Olá {nome}'.format(nome=usuario)
app = Flask(__name__)
from exemplo import blueprint_exemplo
app.register(blueprint_exemplo, url_prefix='/exemplo')
A combinação do blueprint anterior com esse carregamento, gera a URL
/exemplo/say/<usuario>
.
blueprint_exemplo = Blueprint('exemplo', __name__)
exemplo
é o nome do blueprint (para que isso serve, mais adiante)__name__
tem a mesma finalidade do __name__
do app: encontrar módulos/recursos.Tudo que foi visto sobre rotas continua valendo:
@blueprint_exemplo.route('/<int:var1>/<int:var2>', methods=['GET'])
def sum(var1, var2):
return 'Soma = {sum}'.format(sum=var1+var2)
Flask vem com Jinja2 como renderizado de templates.
A sintaxe é muito semelhante ao sistema de templates do Django:
{% for nome in usuarios %}
<div class='usuario'>Olá {{ nome }}<div>
{% endfor %}
Para usar um template, basta usar a função render_template
.
Parâmetros para o template devem ser passados como parâmetros adicionais na função:
from flask import render_template
@app.index('/')
def index():
return render_template('hello-world.html',
usuarios=['Julio', 'Leandro', 'Bruna', 'Cláudio'])
render_template()
é simplesmente um parser de templates com um gerador
de Responses.
(Ou seja, o resultado esperado das funções -- qualquer função -- é um Response.)
(Criar um response especializado é algo que somente e feito em 2% dos casos.)
Por que isso é importante?
Responses tem algumas propriedades a mais, como o tipo do retorno (text/html, por exemplo) e o status.
Para retornar um status diferente de 200:
def index():
resp = render_template('404-not-found.html')
resp.status_code = 404
return resp
Para retornar um tipo diferente, é preciso criar o Response do zero:
def index():
resp = make_response('Olá mundo')
resp.status_code = 200
resp.mimetype = 'text/plain'
Para JSON, já existe uma função pronta:
from flask import jsonify
@app.route('/')
def index():
usuarios=['Julio', 'Leandro', 'Bruna', 'Cláudio']
return jsonify(status='OK',
usuarios=usuarios)
Isso gera o JSON
{status: "OK", usuarios=["Julio", "Leandro", "Bruna", "Claudio"]}
.
Como jsonify()
gera um Response, ele ainda pode ser mexido:
def index():
resp = jsonify(status='ERROR', code='404')
resp.status = 404
return resp
Flask também tem funções para auxiliar na geração de respostas que não são "páginas":
from flask import abort
def index():
abort(404)
Gera um response com status 404 padrão do sistema.
from flask import redirect
def index():
redirect('/correct-path')
Gera um redirectionamento para /correct-path
.
Request contém as informações que estão vindo na requisição:
request.method
: Método HTTP utilizado.request.form
: Dados do formulário com POST/PUT.request.args
: Dados do querystring (GET).request.values
: form + args.request.cookies
: Cookies da página.request.headers
: Headers recebidos.request.files
: Arquivos enviados.request.get_json()
: Parseia a resposta se ela for JSON.
from flask import request # acesso ao objeto de request atual
from flask import abort
from flask import render_template
def index():
nome = request.values.get('usuario')
if not nome:
abort(400) # Bad Request
return render_template('hello-world.html',
usuarios=[nome])
Para mostrar páginas diferentes da default, basta adicionar um errorhandler
.
app = Flask(__name__)
@app.errorhandler(404)
def not_found():
return jsonify(status='ERROR',
message='Not found')
errorhandler
também pode capturar excessões:
from flask import Flask
from mongoengine import NotFoundError
app = Flask(__name__)
@app.errorhandler(NotFoundError)
def not_found():
return jsonify(status='ERROR',
message='Mongo object not found')
Isso captura qualquer ocorrência de NotFoundError
, inclusive
dentro dos blueprints.
Configurações podem vir de 3 lugares diferentes:
Todos os três podem ser executados em sequência, o último valor encontrado é o que vale.
class Settings(objects):
FILE_PATH = './here'
ORDER_FIELD = 'name'
app = Flask(__name__)
app.config.from_object(Settings)
app.config.from_pyfile('/etc/meuaplicativo.cfg')
app.config.from.envvar('MEUAPLICATIVO_CFG')
Se eu posso registrar um Blueprint com qualquer prefixo, como eu descubro depois qual a URL de um recurso (se eu precisar fazer um redirect)?
url_for()
url_for()
recebe um endpoint e retorna a URL para aquele endpoint.
O que diabos é um endpoint?
@app.route('/')
def index():
return 'Olá mundo'
Endpoint = index
exemplo = Blueprint('meuexemplo', __name__)
@exemplo.route('/')
def index():
return 'Olá mundo'
Endpoint = meuexemplo.index
exemplo = Blueprint('meuexemplo', __name__)
@exemplo.route('/')
def index():
return redirect(url_for('meuexemplo.list'))
@exemplo.route('/list')
def list():
return 'Olá todos vocês.'
Se registrar o Blueprint com prefix = /exemplo
, o index()
irá
fazer um redirect para /exemplo/list
.
Se registrar o Blueprint com prefix = /
, o index()
irá
fazer um redirect para /list
.
url_for()
também funciona dentro de templates.
<button onClick='redirect("{{ url_for('meuexemplo.list') }}")'>
Flask vem com um servidor de desenvolvimento integrado. Para utilizar:
app.run()
Ou ainda:
if __name__ == '__main__':
app.run()