Flask
Apparence
Liens
- Flask Bootstrap
- Handling modal forms with Flask
- Bootstrap Edit table row
- Creating a Web App using Flask and Ajax
Exemple
mywebsite.py |
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html', title='Hello', text='Some text to display')
if __name__ == '__main__':
app.run(debug=True)
|
templates/index.html |
<head>
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
</head>
<body>
<h1>{{ title }}</h1>
<p>
{{ text }}
</p>
|
Jinja2
{{ my_variable }}
{{ my_object.my_attribute }}
{{ my_object.my_method() }}
{% if my_variable > 0 %}
{% elif my_variable < 10 %}
{% else %}
{% endif %}
<a href="{{ url_for('my_page') }}">My Page</a>
|
@app.route('/my-page-1') # nom de l'url libre, mais @app.route doit décorer la méthode
def my_page(): # le nom de la méthode doit correspondre au nom utilisé dans url_for
return 'My Page !!!'
|
Héritage de templates
base.html |
<!-- définit un block vide ou non qui sera rempli, remplacé ou complété dans les templates enfants -->
{% block content %}
{% endblock %}
|
my_page.html |
<!-- hérite du template parent -->
{% extends "base.html" %}
<!-- écrase le contenu du block content -->
{% block content %}
<p>Some text to display.</p>
<!-- récupère le contenu du block du parent -->
{{super()}}
{% endblock %}
|
Macros
my_macro.html |
{% macro render_field(field) %}
<tr {% if field.errors %} class="error" {% endif %}>
<td>{{ field.label }}</td>
<td>{{ field(**kwargs)|safe }}</td>
</tr>
{% if field.errors %}
<tr>
<td></td>
<td>
<ul class="error">
{% for error in field.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</td>
</tr>
{% endif %}
{% endmacro %}
|
form.html |
{% from "my_macro.html" import render_field %}
<form action="" method="post">
{{ form.hidden_tag() }}
<table>
{{ render_field(form.name, size=50) }}
<tr>
<td></td>
<td><input type="submit" value="Ok"></td>
</tr>
</table>
</form>
|
Custom Filters
@app.template_filter('dateformat')
def dateformat(value, format='%d %B %Y'):
return value.strftime(format)
|
{{ my_object.date|dateformat }} |
Route
@app.route('/')
@app.route('/index')
def index():
return render_template('index.html')
@app.route('/my_page')
def my_page():
return render_template('my_page.html')
# POST
@app.route('/formulaire', methods=('GET', 'POST'))
def formulaire():
if request.method == 'POST':
data = request.form['key'] # récupère l'élément key du formulaire
return redirect(url_for('index')) # retour à index une fois le formulaire validé
return render_template('formulaire.html') # affichage du formulaire
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
|
Flash messages
from flask import flash
# configurer la clé secrète pour permettre l'utilisation de session
app.config['SECRET_KEY'] = '...'
# générer une clé de 24 octets: os.urandom(24)
# enregistre un message dans la session
flash('Some message.')
|
<!-- Au chargement de la page, on récupère et affiche tous les messages -->
<article>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
</article>
|
Flask-WTF 0.14.2
Liens
Flask-WTF Exemple
![]() |
Penser à utiliser la macro render_field |
main.py |
from flask_wtf import FlaskForm
from wtforms.fields import StringField, DateField, SelectField
from wtforms.validators import DataRequired
class MyForm(FlaskForm):
name = StringField('The name:', validators=[DataRequired()], size=50)
date = DateField('Date:', validators=[DataRequired()], format='%d %B %Y', size=50)
country = SelectField('Country', coerce=int, validators=[DataRequired()], style='width:465px;')
# coerc pour convertir la value str → int
# pour la balise select, size définit le nombre d'éléments sélectionnable et non la longueur
def __init__(self, *args, **kwargs): # permet de définir la liste de choix pour country
super(MyForm, self).__init__(**kwargs)
self.country.choices = [(k, v.name) for k, v in all_countries.items()] # (value, label) pairs
def validate(self): # custom validation
if self.name.data and self.name.data[0].isupper(): # test si le nom commence par une majuscule
return super().validate() # appel les autres validateurs
else:
return False
@app.route('/edit/<id>', methods=('GET', 'POST'))
def edit(id):
my_object = ... # récupère l'objet à éditer
if request.method == 'GET':
my_form = MyForm(obj=my_object)
my_form.country.data = my_object.country.id_country
else:
my_form = MyForm()
if my_form.validate_on_submit():
my_form.populate_obj(my_object)
my_object.country = all_countries[my_object.country] # ici my_object.country est un int
return redirect('index') # une fois le formulaire validé, redirection vers index
return render_template('edit.html', id=id, form=my_form)
|
edit.html |
<form action="" method="post">
{{ form.hidden_tag() }}
<table class="table">
<tr>
<td>{{ form.name.label }}</td>
<td>{{ form.name(size = 50) }}</td>
</tr>
{% if field.errors %}
<tr>
<td></td>
<td>
<ul>
{% for error in form.name.errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
</td>
</tr>
{% endif %}
<tr>
<td></td>
<td>
<a class="btn btn-default" href="{{ url_for('index') }}">Cancel</a>
<input type="submit" class="btn btn-primary" value="Save changes">
</td>
</tr>
</table>
</form>
|
Flask-SQLAlchemy
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/test.db'
db = SQLAlchemy(app)
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
def __repr__(self):
return '<User %r>' % self.username
|
Flask-Bootstrap
![]() |
|
from flask_bootstrap import Bootstrap
app = Flask(__name__)
Bootstrap(app)
|
{% extends "bootstrap/base.html" %}
{% block styles %}
{{ super() }}
<link rel="stylesheet" href="{{ url_for('static', filename='css/main.css') }}">
{% endblock %}
{% block title %}This is an example page{% endblock %}
{% block content %}
<h1>Hello, Bootstrap</h1>
{% endblock %}
{% block scripts %}
{{ super() }}
<script src="{{ url_for('static', filename='js/main.js') }}"></script>
{% endblock %}
|
Arborescence de fichiers
- mywebsite.py
- static
- css
- img
- js
- templates
- index.html
- 404.html
Model, Template, View
Nom | Équivalent MVC | Description |
---|---|---|
Model | Model | Classes business, stockage des données (SQLAlchemy) |
Template | View | Génération du HTML (Jinja2) |
View | Controller | Gestion des requêtes HTTP et envoie des réponses HTTP Routage et mapping des URL |
Flask-DebugToolbar
sudo pip install flask-debugtoolbar |
from flask_debugtoolbar import DebugToolbarExtension
app = Flask(__name__)
app.debug = True
app.config['SECRET_KEY'] = b'...'
app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False
toolbar = DebugToolbarExtension(app)
|
Installation
pacman -S python-flask python-flask-wtf python-flask-sqlalchemy |