Flask: Microframework para construção de aplicações web em Python

Preview:

DESCRIPTION

Apresentação interna feita na Giran (http://www.giran.com.br) sobre o Flask, microframework Python para construção de aplicações web.

Citation preview

FlaskMicroframework para construção de

aplicações web em Python

Francisco Souza@franciscosouzafrancisco@franciscosouza.netwww.franciscosouza.com.br

Micro?

http://www.flickr.com/photos/waisian/3590682463/

http://www.flickr.com/photos/benchilada/2467374335/

Mais um framework?

Por que usar um microframework?

Simplicidade

http://www.flickr.com/photos/payayita/3313899667/

é

simples.

mas o

django helloworld

3 comandos2 linhas de configuração3 linhas de código

Bônus

http://www.flickr.com/photos/malingering/58838080/

Flexibilidade

http://www.flickr.com/photos/wainwright/351684037/

from flask import Flask

app = Flask('hello')

@app.route('/hello')def hello(): return 'Hello world'

app.run()

Simples,leve e

pequeno.

Não subestime os pequenos

http://www.flickr.com/photos/st3f4n/4406339573/

Flask não é full stack

Acoplamento

http://www.flickr.com/photos/inertiacreeps/1414772429/

Deixe um framework de persistência cuidar do seu banco de dados...

Deixe um framework de persistência cuidar do seu banco de dados...

seja lá qual for seu banco de dados.

Deixe um framework de persistência cuidar do seu banco de dados...

seja lá qual for seu banco de dados.

Extensível

Extensões para...FormuláriosBancos de dadosTestesi18n CachingCSRFTemplating...

http://www.flickr.com/photos/ntrlwmn/4103357982/

Bônus!

Um CRUD cairia bem...

$ pip install Flask Flask-WTF Flask-SQLAlchemy$ mkdir projetos$ cd projetos$ mkdir templates$ touch projetos.py

Um CRUD cairia bem...

$ pip install Flask Flask-WTF Flask-SQLAlchemy$ mkdir projetos$ cd projetos$ mkdir templates$ touch projetos.py

Criação da aplicação

from flask import Flask

app = Flask(__name__)

Banco de dados, com SQLAlchemy

from flaskext.sqlalchemy import SQLAlchemy

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///dados.sqlite3'db = SQLAlchemy(app)

class Projeto(db.Model): __tablename__ = 'projetos' id = db.Column(db.Integer, primary_key = True) nome = db.Column(db.String(100), nullable = False) descricao = db.Column(db.Text, nullable = False)

Formulários, com WTForms

from flaskext import wtf

app.config['SECRET_KEY'] = 'HSAOIHs8ashw8JSJ'app.config['CSRF_ENABLED'] = Trueapp.config['CSRF_SESSION_KEY'] = 'HSAOIHs8ashw8JSJwtforms'

class ProjetoForm(wtf.Form): nome = wtf.TextField(u'Nome', validators=[wtf.Required()]) descricao = wtf.TextAreaField(u'Descrição',

validators=[wtf.Required()])

Formulários a partir de

modelos

http://www.flickr.com/photos/cayusa/981372736/

View para exibição do formulário

from flask import render_template

@app.route('/novo_projeto')def novo_projeto(): formulario = ProjetoForm() return render_template('novo_projeto.html', form=formulario)

Template, com Jinja2

<html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <title>Novo projeto</title> </head> <body id=""> <h1 id="">Cadastro de novo Projeto</h1> <form action="" method="post" accept-charset="utf-8"> {{ form.csrf_token }} <p><label for="nome">{{ form.nome.label }}:</label><br /> {{ form.nome() }}</p> <p><label for="descricao">{{ form.descricao.label }}:</label><br /> {{ form.descricao() }}</p> <p><input type="submit" value="Cadastrar"/></p> </form> </body></html>

Template, com Jinja2

<html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <title>Novo projeto</title> </head> <body id=""> <h1 id="">Cadastro de novo Projeto</h1> <form action="" method="post" accept-charset="utf-8"> {{ form.csrf_token }} <p><label for="nome">{{ form.nome.label }}:</label><br /> {{ form.nome() }}</p> <p><label for="descricao">{{ form.descricao.label }}:</label><br /> {{ form.descricao() }}</p> <p><input type="submit" value="Cadastrar"/></p> </form> </body></html>

Don't repeat yourself!

● Jinja2 macros

Macro para renderizar campo do formulário

{% macro render_field(field) %} <p><label for="{{ field.id }}">{{ field.label }}:<br /> {{ field(**kwargs)|safe }} {% if field.errors %} <ul class="errors"> {% for error in field.errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} </p>{% endmacro %}

Template, com Jinja2

<html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <title>Novo projeto</title> </head> <body id=""> <h1 id="">Cadastro de novo Projeto</h1> <form action="" method="post" accept-charset="utf-8"> {{ form.csrf_token }} <p><label for="nome">{{ form.nome.label }}:</label><br /> {{ form.nome() }}</p> <p><label for="descricao">{{ form.descricao.label }}:</label><br /> {{ form.descricao() }}</p> <p><input type="submit" value="Cadastrar"/></p> </form> </body></html>

Template, com Jinja2 Macro

<html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <title>Novo projeto</title> </head> <body id=""> <h1 id="">Cadastro de novo Projeto</h1> <form action="" method="post" accept-charset="utf-8"> {{ form.csrf_token }} {{ render_field(form.nome) }}

{{ render_field(form.descricao) }}

<p><input type="submit" value="Cadastrar"/></p> </form> </body></html>

Estendendo a view para receber dados do

formulário

from flask import render_template

@app.route('/novo_projeto')def novo_projeto(): formulario = ProjetoForm() return render_template('novo_projeto.html', form=formulario)

Estendendo a view para receber dados do

formulário

from flask import render_template

@app.route('/novo_projeto', methods = ['GET', 'POST'])def novo_projeto(): formulario = ProjetoForm() return render_template('novo_projeto.html', form=formulario)

RESTful URL routing

Utilíssimo para criação de APIs =)

RESTful URL routing

Utilíssimo para criação de APIs =)

Problemático para trabalhar com formulários.

HTML 5?

Estendendo a view para receber dados do

formulário

from flask import render_template

@app.route('/novo_projeto', methods = ['GET', 'POST'])def novo_projeto(): formulario = ProjetoForm() if formulario.validate_on_submit(): projeto = Projeto() projeto.nome = formulario.nome.data projeto.descricao = formulario.descricao.data db.session.add(projeto) db.session.commit() return redirect(url_for('listar_projetos')) return render_template('novo_projeto.html', form=formulario)

View para listagem dos projetos

@app.route('/projetos')def listar_projetos(): projetos = Projeto.query.all() return render_template('projetos.html', projetos=projetos)

Template para listagem

<html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <title>Listagem de projetos</title> </head> <body id=""> <h1 id="">Listagem de projetos</h1> <ul> {% for projeto in projetos %} <li>{{ projeto.nome }}</li> {% endfor %} </ul> </body></html>

Template para listagem

<html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <title>Listagem de projetos</title> </head> <body id=""> <h1 id="">Listagem de projetos</h1> <ul> {% for projeto in projetos %} <li>{{ projeto.nome }}</li> {% endfor %} </ul> </body></html>

Don't repeat yourself!

● Jinja2 macros● Herança de templates

Template base para herança

<html> <head> <meta http-equiv="Content-type" content="text/html; charset=utf-8"/> <title>{% block titulo %}{% endblock %}</title> </head> <body id=""> {% block conteudo %}{% endblock %} </body></html>

Template de formulário refatorado

{% extends "base.html" %}{% block titulo %} Cadastro de novo Projeto{% endblock %}

{% block conteudo %} <h1 id="">Cadastro de novo Projeto</h1> <form action="" method="post" accept-charset="utf-8"> {{ form.hidden_tag() }} {{ render_field(form.nome) }} {{ render_field(form.descricao) }} <p><input type="submit" value="Cadastrar"/></p> </form>{% endblock %}

Template de listagem refatorado

{% extends "base.html" %}{% block titulo %} Listagem de projetos{% endblock %}

{% block conteudo %} <h1 id="">Listagem de projetos</h1> <ul> {% for projeto in projetos %} <li>{{ projeto.nome }}</li> {% endfor %} </ul>{% endblock %}

Executando a aplicação

$ python projetos.py

E agora?

http://www.flickr.com/photos/smart-trips/4047872730/

E agora?

http://www.flickr.com/photos/smart-trips/4047872730/

flask.pocoo.org

E agora?

http://www.flickr.com/photos/smart-trips/4047872730/

flask.pocoo.org

werkzeug.pocoo.org

E agora?

http://www.flickr.com/photos/smart-trips/4047872730/

flask.pocoo.org

werkzeug.pocoo.org

jinja.pocoo.org/2

Francisco Souza@franciscosouza

www.franciscosouza.com.br

Recommended