From 6d11b469806ff4ecfaee48362b6d91ad7bc73922 Mon Sep 17 00:00:00 2001 From: Julio Biason Date: Mon, 30 Jun 2014 18:27:45 -0300 Subject: [PATCH] completed the flask presentation --- flask.html | 682 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 560 insertions(+), 122 deletions(-) diff --git a/flask.html b/flask.html index ac5b1f4..0d33bfa 100644 --- a/flask.html +++ b/flask.html @@ -1,86 +1,86 @@ - - + + - Flask + Flask - + - - + + - + - - + + - - + + - - + + - + - - + + - + -
- -
-
-

Flask

-
+
+ +
+
+

Flask

+
-
-

O que é Flask?

+
+

O que é Flask?

-
    -
  • Microframework web em Python.
  • -
  • Framework sobre o Werkzeug (outro framework).
  • -
  • Sem ORM, mas templates.
  • -
-
+
    +
  • Microframework web em Python.
  • +
  • Framework sobre o Werkzeug (outro framework).
  • +
  • Sem ORM, mas templates.
  • +
+
-
-
-

Aplicativo Flask Básico

+
+
+

Aplicativo Flask Básico

-


+                        


 from flask import Flask
 app = Flask(__name__)
 
 @app.route('/')
 def index():
-	return 'Hello world'
-						

-
+ return 'Hello world' +

+
-
-


+                    
+


 #!/usr/bin/env python
 # -*- encoding: utf-8 -*-
 
@@ -89,13 +89,13 @@ app = Flask(__name__)
 
 @app.route('/')
 def index():
-	return 'Hello world'
-						

-

... mais o header...

-
+ return 'Hello world' +

+

... mais o header...

+
-
-


+                    
+


 #!/usr/bin/env python
 # -*- encoding: utf-8 -*-
 
@@ -106,13 +106,13 @@ app = Flask(__name__)
 
 @app.route('/')
 def index():
-	return 'Hello world'
-						

-

... mais a documentação do módulo...

-
+ return 'Hello world' +

+

... mais a documentação do módulo...

+
-
-


+                    
+


 #!/usr/bin/env python
 # -*- encoding: utf-8 -*-
 
@@ -123,15 +123,15 @@ app = Flask(__name__)
 
 @app.route('/')
 def index():
-	"""Apresentação do 'root' do aplicativo."""
-	return 'Hello world'
-						

+ """Apresentação do 'root' do aplicativo.""" + return 'Hello world' +

-

... mais a documentação das funções...

-
+

... mais a documentação das funções...

+
-
-


+                    
+


 #!/usr/bin/env python
 # -*- encoding: utf-8 -*-
 
@@ -144,22 +144,22 @@ app = Flask(__name__)
 
 @app.route('/')
 def index():
-	"""Apresentação do 'root' do aplicativo."""
-	return render_template('hello.html')
-						

+ """Apresentação do 'root' do aplicativo.""" + return render_template('hello.html') +

-

... mais retornar templates ao invés de texto puro...

-
+

... 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'
+    SECRET_KEY = 'Sup3rs3cr33t'
 
 from flask import Flask
 from flask import render_template
@@ -171,58 +171,496 @@ app.config.from_envvar('MEU_APLICATIVO_CONFIG')
 
 @app.route('/')
 def index():
-	"""Apresentação do 'root' do aplicativo."""
-	return render_template('hello.html')
-						

+ """Apresentação do 'root' do aplicativo.""" + return render_template('hello.html') +

-

... mais adicionar uma configuração...

-
+

... mais adicionar uma configuração...

+ -
-

... mais tratamento de erros...

+
+

... mais tratamento de erros...

-

... mais outras rotas...

+

... mais outras rotas...

-

... mais blueprints/applications...

+

... mais blueprints/applications...

-

... mais inicialização do ORM...

-
-
+

... mais inicialização do ORM...

+ + -
- -
-
-
+
+ +
- - +
+

Criando uma app

- +
+
+

Templates

+
- +
+

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'])
+                        

+
+
+ +
+
+

Responses

+
+ +
+

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.

+
+
+ +
+
+

Requests

+
+ +
+

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])
+                        

+
+
+ +
+
+

Tratamento de erros

+
+ +
+

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.

+
+
+ +
+
+

URLs reversas/Endpoints

+
+ +
+

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') }}")'>
+                        

+
+
+ +
+
+

Resumo

+
+ +
+
    +
  • Sintaxe simples (a sintaxe foi uma brincadeira de 1o. de abril)
  • +
  • Controle centralizado de erros.
  • +
  • Total controle sobre as respostas.
  • +
  • Acesso total ao request.
  • +
  • Módulos completamente isolados mas ainda permite que esses sejam + conectados por endpoints.
  • +
  • Não comentado, mas o Werkzeug também expõe todo o controle da aplicação.
  • +
  • Ainda não tem um ORM integrado, mas é fácil de plugar qualquer um.
  • +
  • Pythônico.
  • +
+
+
+ +
+
+
+
+
+ + + + + + +