Bien débuter

Vous avez hâte de commencer ? Cette page donne une bonne introduction à Flask. Suivez Installation pour mettre en place un projet et installer Flask.

Une application minimale

Une application Flask minimale ressemble à quelque chose comme ceci :

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

Alors, que fait ce code ?

  1. D’abord nous avons importé la classe Flask. Une instance de cette classe sera notre application WSGI.

  2. Ensuite, nous créons une instance de cette classe. Le premier argument est le nom du module ou du paquet de l’application. __name__ est un raccourci pratique qui est approprié pour la plupart des cas. Ceci est nécessaire pour que Flask sache où chercher les ressources telles que les modèles et les fichiers statiques.

  3. Nous utilisons ensuite le décorateur route() pour indiquer à Flask quelle URL doit déclencher notre fonction.

  4. Cette fonction renvoie le message que nous voulons afficher dans le navigateur de l’utilisateur. Le type de contenu par défaut est du HTML, donc le HTML dans la chaîne de caractères sera rendu par le navigateur.

Enregistrez-le sous le nom de hello.py ou quelque chose de similaire. Veillez à ne pas appeler votre application flask.py car cela entrerait en conflit avec Flask lui-même.

Pour démarrer l’application, utilisez la commande flask ou python -m flask. Avant de faire cela, vous devez indiquer à votre terminal l’application avec laquelle travailler en exportant la variable d’environnement FLASK_APP :

$ export FLASK_APP=hello
$ flask run
 * Running on http://127.0.0.1:5000/

Détection automatique de l’application

Si le fichier est nommé app.py ou wsgi.py, vous n’avez pas besoin de définir la variable d’environnement FLASK_APP. Voir Command Line Interface pour plus de détails.

Ceci lance un serveur intégré très simple, qui est suffisant pour les tests mais probablement pas ce que vous voulez utiliser en production. Pour les options de déploiement, voir Deployment Options.

Maintenant, allez sur http://127.0.0.1:5000/, et vous devriez voir votre message d’accueil « Hello, World! ».

Serveur visible de l’extérieur

Si vous démarrez le serveur, vous remarquerez qu’il n’est accessible que depuis votre propre ordinateur, et non depuis un autre ordinateur du réseau. Il s’agit de la valeur par défaut car, en mode débogage, un utilisateur de l’application peut exécuter un code Python arbitraire sur votre ordinateur.

Si vous avez désactivé le débogueur ou si vous faites confiance aux utilisateurs de votre réseau, vous pouvez rendre le serveur accessible au public simplement en ajoutant --host=0.0.0.0 à la ligne de commande :

$ flask run --host=0.0.0.0

Cela indique à votre système d’exploitation d’écouter sur toutes les adresses IP publiques.

Que faire si le serveur ne démarre pas

Si la commande python -m flask échoue ou si la commande flask n’existe pas, il y a plusieurs raisons pour lesquelles cela peut être le cas. Tout d’abord, vous devez examiner le message d’erreur.

Ancienne version de Flask

Les versions de Flask antérieures à la 0.11 avaient différentes façons de démarrer l’application. En bref, la commande flask n’existait pas, ni la commande python -m flask. Dans ce cas, vous avez deux options : soit vous mettez à jour vers des versions plus récentes de Flask, soit vous jetez un coup d’oeil à Development Server pour voir la méthode alternative pour faire tourner un serveur.

Nom d’importation non valide

La variable d’environnement FLASK_APP est le nom du module à importer dans flask run. Si ce module est mal nommé, vous obtiendrez une erreur d’importation au démarrage (ou si le débogage est activé lorsque vous naviguez dans l’application). Il vous dira ce qu’il a essayé d’importer et pourquoi il a échoué.

La raison la plus courante est une faute de frappe ou le fait que vous n’ayez pas réellement créé un objet « application ».

Mode débogage

La commande flask run peut faire plus que simplement démarrer le serveur de développement. En activant le mode débogage, le serveur se rechargera automatiquement si le code change, et affichera un débogueur interactif dans le navigateur si une erreur se produit pendant une requête.

Le débogueur interactif en action.

Avertissement

Le débogueur permet d’exécuter du code Python arbitraire depuis le navigateur. Il est protégé par un PIN, mais représente tout de même un risque de sécurité important. N’exécutez pas le serveur de développement ou le débogueur dans un environnement de production.

Pour activer toutes les fonctionnalités de développement, définissez la variable d’environnement FLASK_ENV à development avant d’appeler flask run.

$ export FLASK_ENV=development
$ flask run

Voir aussi:

L’échappement HTML

Lorsque vous renvoyez du HTML (le type de réponse par défaut dans Flask), toute valeur fournie par l’utilisateur et rendue dans la réponse doit être échappée pour se protéger des attaques par injection. Les modèles HTML rendus avec Jinja, introduits plus tard, le feront automatiquement.

escape(), montré ici, peut être utilisé manuellement. Il est omis dans la plupart des exemples pour des raisons de brièveté, mais vous devriez toujours être conscient de la façon dont vous utilisez les données non fiables.

from markupsafe import escape

@app.route("/<name>")
def hello(name):
    return f"Hello, {escape(name)}!"

Si un utilisateur a réussi à soumettre le nom <script>alert("bad")</script>, l’échappement fait en sorte qu’il soit rendu comme du texte, plutôt que d’exécuter le script dans le navigateur de l’utilisateur.

<name> dans la route capture une valeur de l’URL et la passe à la fonction de vue. Ces règles de variables sont expliquées ci-dessous.

Routage

Les applications web modernes utilisent des URL significatives pour aider les utilisateurs. Les utilisateurs sont plus susceptibles d’aimer une page et de revenir si la page utilise une URL significative qu’ils peuvent mémoriser et utiliser pour visiter directement une page.

Utilisez le décorateur route() pour lier une fonction à une URL :

@app.route('/')
def index():
    return 'Index Page'

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

Vous pouvez faire plus ! Vous pouvez rendre certaines parties de l’URL dynamiques et attacher plusieurs règles à une fonction.

Règles variables

Vous pouvez ajouter des sections variables à une URL en marquant les sections avec <variable_name>. Votre fonction reçoit alors <variable_name> comme un argument nommé. En option, vous pouvez utiliser un convertisseur pour spécifier le type de l’argument comme <converter:variable_name> :

from markupsafe import escape

@app.route('/user/<username>')
def show_user_profile(username):
    # show the user profile for that user
    return f'User {escape(username)}'

@app.route('/post/<int:post_id>')
def show_post(post_id):
    # show the post with the given id, the id is an integer
    return f'Post {post_id}'

@app.route('/path/<path:subpath>')
def show_subpath(subpath):
    # show the subpath after /path/
    return f'Subpath {escape(subpath)}'

Types de convertisseurs :

string

(par défaut) accepte tout texte sans slash

int

accepte les nombres entiers positifs

float

accepte les valeurs positives à virgule flottante

path

comme string mais accepte aussi les slashs

uuid

accepte les chaînes UUID

URLs uniques / Comportement de redirection

Les deux règles suivantes diffèrent par l’utilisation d’une barre oblique de fin de ligne :

@app.route('/projects/')
def projects():
    return 'The project page'

@app.route('/about')
def about():
    return 'The about page'

L’URL canonique du point de terminaison projects comporte un slash de fin. C’est similaire à un dossier dans un système de fichiers. Si vous accédez à l’URL sans slash de fin (/projets), Flask vous redirige vers l’URL canonique avec le slash de fin (/projets/).

L’URL canonique du point de terminaison about ne comporte pas de barre oblique de fin de ligne. Elle est similaire au chemin d’accès d’un fichier. L’accès à l’URL avec un slash de fin (/about/) produit une erreur 404 « Not Found ». Cela permet de conserver des URL uniques pour ces ressources, ce qui aide les moteurs de recherche à ne pas indexer deux fois la même page.

Création d’URL

Pour construire une URL vers une fonction spécifique, utilisez la fonction url_for(). Elle accepte le nom de la fonction comme premier argument et un nombre quelconque d’arguments nommés, chacun correspondant à une partie variable de l’URL. Les parties variables inconnues sont ajoutées à l’URL comme paramètres de requête.

Pourquoi voudriez-vous construire des URL en utilisant la fonction d’inversion d’URL url_for() au lieu de les coder en dur dans vos modèles ?

  1. L’inversion est souvent plus descriptive que le codage en dur des URL.

  2. Vous pouvez modifier vos URL en une seule fois au lieu de devoir vous souvenir de modifier manuellement les URL codées en dur.

  3. La construction d’URL gère l’échappement des caractères spéciaux de manière transparente.

  4. Les chemins générés sont toujours absolus, ce qui évite le comportement inattendu des chemins relatifs dans les navigateurs.

  5. Si votre application est placée en dehors de la racine de l’URL, par exemple, dans /myapplication au lieu de /, url_for() gère cela correctement pour vous.

Par exemple, ici nous utilisons la méthode test_request_context() pour essayer url_for(). test_request_context() indique à Flask de se comporter comme s’il traitait une requête même si nous utilisons un shell Python. Voir Contextes locaux.

from flask import url_for

@app.route('/')
def index():
    return 'index'

@app.route('/login')
def login():
    return 'login'

@app.route('/user/<username>')
def profile(username):
    return f'{username}\'s profile'

with app.test_request_context():
    print(url_for('index'))
    print(url_for('login'))
    print(url_for('login', next='/'))
    print(url_for('profile', username='John Doe'))
/
/login
/login?next=/
/user/John%20Doe

Méthodes HTTP

Les applications Web utilisent différentes méthodes HTTP pour accéder aux URL. Vous devez vous familiariser avec les méthodes HTTP lorsque vous travaillez avec Flask. Par défaut, une route ne répond qu’aux requêtes GET. Vous pouvez utiliser l’argument methods du décorateur route() pour gérer différentes méthodes HTTP.

from flask import request

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        return do_the_login()
    else:
        return show_the_login_form()

Si GET est présent, Flask ajoute automatiquement le support de la méthode HEAD et traite les requêtes HEAD selon la HTTP RFC. De même, OPTIONS est automatiquement implémenté pour vous.

Fichiers statiques

Les applications web dynamiques ont également besoin de fichiers statiques. C’est généralement de là que proviennent les fichiers CSS et JavaScript. Idéalement, votre serveur web est configuré pour les servir à votre place, mais pendant le développement, Flask peut aussi le faire. Il suffit de créer un dossier appelé static dans votre pacquet ou à côté de votre module et il sera disponible à /static sur l’application.

Pour générer des URL pour les fichiers statiques, utilisez le nom de point de terminaison spécial 'static' :

url_for('static', filename='style.css')

Le fichier doit être stocké sur le système de fichiers sous le nom de static/style.css.

Modèles de rendu

Générer du HTML à partir de Python n’est pas amusant, et en fait assez encombrant car vous devez faire l’échappement HTML par vous-même pour garder l’application sécurisée. C’est pourquoi Flask configure automatiquement le moteur de template Jinja2 pour vous.

Pour rendre un modèle, vous pouvez utiliser la méthode render_template(). Tout ce que vous avez à faire est de fournir le nom du modèle et les variables que vous voulez passer au moteur de modèle comme arguments nommés. Voici un exemple simple de la façon de rendre un modèle:

from flask import render_template

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

Flask va chercher les modèles dans le dossier templates. Donc si votre application est un module, ce dossier est à côté de ce module, si c’est un paquet, il est en fait à l’intérieur de votre paquet:

Case 1 : un module:

/application.py
/templates
    /hello.html

Cas 2 : un paquet:

/application
    /__init__.py
    /templates
        /hello.html

Pour les modèles, vous pouvez utiliser toute la puissance des modèles Jinja2. Rendez-vous sur le site officiel Jinja2 Template Documentation pour plus d’informations.

Voici un exemple de modèle :

<!doctype html>
<title>Hello from Flask</title>
{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello, World!</h1>
{% endif %}

À l’intérieur des modèles, vous avez également accès aux objets config, request, session et g 1 ainsi qu’aux fonctions url_for() et get_flashed_messages().

Les modèles sont particulièrement utiles si l’on utilise l’héritage. Si vous voulez savoir comment cela fonctionne, consultez Template Inheritance. En fait, l’héritage des modèles permet de conserver certains éléments sur chaque page (comme l’en-tête, la navigation et le pied de page).

L’échappement automatique est activé, donc si name contient du HTML, il sera automatiquement échappé. Si vous pouvez faire confiance à une variable et que vous savez que ce sera du HTML sûr (par exemple parce qu’elle provient d’un module qui convertit le balisage wiki en HTML), vous pouvez la marquer comme sûre en utilisant la classe Markup ou en utilisant le filtre |safe dans le modèle. Consultez la documentation de Jinja 2 pour plus d’exemples.

Voici une introduction de base au fonctionnement de la classe Markup:

>>> from markupsafe import Markup
>>> Markup('<strong>Hello %s!</strong>') % '<blink>hacker</blink>'
Markup('<strong>Hello &lt;blink&gt;hacker&lt;/blink&gt;!</strong>')
>>> Markup.escape('<blink>hacker</blink>')
Markup('&lt;blink&gt;hacker&lt;/blink&gt;')
>>> Markup('<em>Marked up</em> &raquo; HTML').striptags()
'Marked up \xbb HTML'
Changelog

Modifié dans la version 0.5: L’échappement automatique n’est plus activé pour tous les modèles. Les extensions suivantes pour les modèles déclenchent l’échappement automatique : .html, .htm, .xml, .xhtml. L’échappement automatique est désactivé pour les modèles chargés à partir d’une chaîne de caractères.

1

Vous ne savez pas ce qu’est l’objet g ? C’est un objet dans lequel vous pouvez stocker des informations pour vos propres besoins. Consultez la documentation de flask.g et de Using SQLite 3 with Flask.

Accès aux données de la requête

Pour les applications web, il est crucial de réagir aux données qu’un client envoie au serveur. Dans Flask, ces informations sont fournies par l’objet global request. Si vous avez une certaine expérience de Python, vous vous demandez peut-être comment cet objet peut être global et comment Flask parvient à rester threadsafe. La réponse est : les contextes locaux :

Contextes locaux

Informations pour les initiés

Si vous voulez comprendre comment cela fonctionne et comment vous pouvez mettre en œuvre des tests avec des contextes locaux, lisez cette section, sinon passez-la.

Certains objets dans Flask sont des objets globaux, mais pas du genre habituel. Ces objets sont en fait des proxies d’objets qui sont locaux à un contexte spécifique. Quelle belle expression ! Mais c’est en fait assez facile à comprendre.

Imaginez que le contexte soit le thread de traitement. Une requête arrive et le serveur web décide de créer un nouveau thread (ou autre chose, l’objet sous-jacent est capable de gérer des systèmes de concurrence autres que les threads). Lorsque Flask démarre son traitement interne des demandes, il détermine que le thread actuel est le contexte actif et lie l’application actuelle et les environnements WSGI à ce contexte (thread). Il le fait de manière intelligente afin qu’une application puisse invoquer une autre application sans rupture.

Qu’est-ce que cela signifie pour vous ? En fait, vous pouvez ignorer complètement que c’est le cas, à moins que vous ne fassiez des tests unitaires. Vous remarquerez que le code qui dépend d’un objet requête sera soudainement interrompu parce qu’il n’y a pas d’objet requête. La solution consiste à créer vous-même un objet requête et à le lier au contexte. La solution la plus simple pour les tests unitaires est d’utiliser le gestionnaire de contexte test_request_context(). En combinaison avec l’instruction with, il liera une requête de test afin que vous puissiez interagir avec elle. Voici un exemple :

from flask import request

with app.test_request_context('/hello', method='POST'):
    # now you can do something with the request until the
    # end of the with block, such as basic assertions:
    assert request.path == '/hello'
    assert request.method == 'POST'

L’autre possibilité est de passer un environnement WSGI entier à la méthode request_context() :

with app.request_context(environ):
    assert request.method == 'POST'

L’objet Requête

L’objet requête est documenté dans la section API et nous ne le couvrirons pas ici en détail (voir Request). Voici une vue d’ensemble de certaines des opérations les plus courantes. Tout d’abord, vous devez l’importer depuis le module flask: :

from flask import request

La méthode de la requête actuelle est disponible en utilisant l’attribut method. Pour accéder aux données de formulaire (données transmises dans une requête POST ou PUT), vous pouvez utiliser l’attribut form. Voici un exemple complet des deux attributs mentionnés ci-dessus : :

@app.route('/login', methods=['POST', 'GET'])
def login():
    error = None
    if request.method == 'POST':
        if valid_login(request.form['username'],
                       request.form['password']):
            return log_the_user_in(request.form['username'])
        else:
            error = 'Invalid username/password'
    # the code below is executed if the request method
    # was GET or the credentials were invalid
    return render_template('login.html', error=error)

Que se passe-t-il si la clé n’existe pas dans l’attribut form ? Dans ce cas, un KeyError spécial est généré. Vous pouvez l’attraper comme une KeyError standard mais si vous ne le faites pas, une page d’erreur HTTP 400 Bad Request est affichée à la place. Ainsi, dans de nombreuses situations, vous n’avez pas à faire face à ce problème.

Pour accéder aux paramètres soumis dans l’URL (?key=value), vous pouvez utiliser l’attribut args: :

searchword = request.args.get('key', '')

Nous recommandons d’accéder aux paramètres de l’URL avec get ou en attrapant le KeyError car les utilisateurs peuvent changer l’URL et leur présenter une page 400 bad request dans ce cas n’est pas convivial.

Pour une liste complète des méthodes et des attributs de l’objet requête, consultez la documentation de la Request.

Téléchargements de fichiers

Vous pouvez gérer les fichiers téléchargés avec Flask facilement. Veillez simplement à ne pas oublier de définir l’attribut enctype="multipart/form-data" sur votre formulaire HTML, sinon le navigateur ne transmettra pas du tout vos fichiers.

Les fichiers téléchargés sont stockés en mémoire ou dans un emplacement temporaire du système de fichiers. Vous pouvez accéder à ces fichiers en consultant l’attribut files de l’objet requête. Chaque fichier téléchargé est stocké dans ce dictionnaire. Il se comporte comme un objet Python standard file, mais il possède également une méthode save() qui vous permet de stocker ce fichier sur le système de fichiers du serveur. Voici un exemple simple montrant comment cela fonctionne :

from flask import request

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        f.save('/var/www/uploads/uploaded_file.txt')
    ...

Si vous voulez savoir comment le fichier a été nommé sur le client avant d’être téléchargé dans votre application, vous pouvez accéder à l’attribut filename. Cependant, gardez à l’esprit que cette valeur peut être falsifiée et que vous ne devez donc jamais vous y fier. Si vous voulez utiliser le nom de fichier du client pour stocker le fichier sur le serveur, passez-le par la fonction secure_filename() que Werkzeug vous fournit : :

from werkzeug.utils import secure_filename

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        file = request.files['the_file']
        file.save(f"/var/www/uploads/{secure_filename(f.filename)}")
    ...

Pour de meilleurs exemples, voir Uploading Files.

Cookies

Pour accéder aux cookies, vous pouvez utiliser l’attribut cookies. Pour définir les cookies, vous pouvez utiliser la méthode set_cookie des objets réponses. L’attribut cookies des objets requêtes est un dictionnaire contenant tous les cookies que le client transmet. Si vous souhaitez utiliser des sessions, n’utilisez pas directement les cookies mais plutôt les Sessions de Flask qui ajoutent une certaine sécurité en plus des cookies pour vous.

Cookies de lecture :

from flask import request

@app.route('/')
def index():
    username = request.cookies.get('username')
    # use cookies.get(key) instead of cookies[key] to not get a
    # KeyError if the cookie is missing.

Stockage des cookies :

from flask import make_response

@app.route('/')
def index():
    resp = make_response(render_template(...))
    resp.set_cookie('username', 'the username')
    return resp

Notez que les cookies sont définis sur les objets réponses. Puisque vous ne retournez normalement que des chaînes de caractères depuis les fonctions de vue, Flask les convertira en objets réponses pour vous. Si vous voulez explicitement faire cela, vous pouvez utiliser la fonction make_response() et ensuite la modifier.

Parfois, vous pouvez vouloir définir un cookie à un moment où l’objet réponse n’existe pas encore. Cela est possible en utilisant le motif Deferred Request Callbacks.

Pour cela, voir également A propos des réponses.

Redirections et erreurs

Pour rediriger un utilisateur vers un autre point de terminaison, utilisez la fonction redirect() ; pour interrompre une requête prématurément avec un code d’erreur, utilisez la fonction abort(): :

from flask import abort, redirect, url_for

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/login')
def login():
    abort(401)
    this_is_never_executed()

Cet exemple est plutôt inutile car un utilisateur sera redirigé de l’index vers une page à laquelle il ne peut pas accéder (401 signifie accès refusé) mais il montre comment cela fonctionne.

Par défaut, une page d’erreur en noir et blanc est affichée pour chaque code d’erreur. Si vous voulez personnaliser la page d’erreur, vous pouvez utiliser le décorateur errorhandler(): :

from flask import render_template

@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

Notez le 404 après l’appel render_template(). Cela indique à Flask que le code d’état de cette page doit être 404, ce qui signifie non trouvé. Par défaut, 200 est supposé, ce qui signifie : tout s’est bien passé.

Voir Traitement des erreurs d’application pour plus de détails.

A propos des réponses

La valeur de retour d’une fonction de vue est automatiquement convertie en objet réponse pour vous. Si la valeur de retour est une chaîne de caractères, elle est convertie en un objet réponse avec la chaîne de caractères comme corps de réponse, un code d’état 200 OK et un mimetype : text/html. Si la valeur de retour est un dict, jsonify() est appelé pour produire une réponse. La logique que Flask applique pour convertir les valeurs de retour en objets réponses est la suivante :

  1. Si un objet réponse du type correct est renvoyé, il est directement renvoyé depuis la vue.

  2. S’il s’agit d’une chaîne de caractères, un objet réponse est créé avec ces données et les paramètres par défaut.

  3. Si c’est un dictionnaire, un objet réponse est créé en utilisant jsonify.

  4. Si un tuple est retourné, les éléments du tuple peuvent fournir des informations supplémentaires. De tels tuples doivent être sous la forme (response, status), (response, headers), ou (response, status, headers). La valeur status remplacera le code d’état et headers peut être une liste ou un dictionnaire de valeurs d’en-tête supplémentaires.

  5. Si rien de tout cela ne fonctionne, Flask supposera que la valeur de retour est une application WSGI valide et la convertira en un objet réponse.

Si vous voulez mettre la main sur l’objet réponse résultant dans la vue, vous pouvez utiliser la fonction make_response().

Imaginez que vous ayez une vue comme celle-ci :

from flask import render_template

@app.errorhandler(404)
def not_found(error):
    return render_template('error.html'), 404

Vous devez juste envelopper l’expression de retour avec make_response() et récupérer l’objet réponse pour le modifier, puis le retourner :

from flask import make_response

@app.errorhandler(404)
def not_found(error):
    resp = make_response(render_template('error.html'), 404)
    resp.headers['X-Something'] = 'A value'
    return resp

API avec JSON

Un format de réponse courant lors de l’écriture d’une API est JSON. Il est facile de commencer à écrire une telle API avec Flask. Si vous retournez un dict depuis une vue, il sera converti en réponse JSON.

@app.route("/me")
def me_api():
    user = get_current_user()
    return {
        "username": user.username,
        "theme": user.theme,
        "image": url_for("user_image", filename=user.image),
    }

Selon la conception de votre API, vous pouvez vouloir créer des réponses JSON pour des types autres que dict. Dans ce cas, utilisez la fonction jsonify(), qui sérialise tout type de données JSON pris en charge. Vous pouvez également consulter les extensions de la communauté Flask qui prennent en charge des applications plus complexes.

from flask import jsonify

@app.route("/users")
def users_api():
    users = get_all_users()
    return jsonify([user.to_json() for user in users])

Sessions

En plus de l’objet requête, il existe un second objet appelé session qui permet de stocker des informations spécifiques à un utilisateur d’une requête à l’autre. Cet objet est implémenté par-dessus les cookies et signe les cookies de manière cryptographique. Cela signifie que l’utilisateur peut regarder le contenu de votre cookie mais ne peut pas le modifier, sauf s’il connaît la clé secrète utilisée pour la signature.

Pour utiliser les sessions, vous devez définir une clé secrète. Voici comment les sessions fonctionnent :

from flask import session

# Set the secret key to some random bytes. Keep this really secret!
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

@app.route('/')
def index():
    if 'username' in session:
        return f'Logged in as {session["username"]}'
    return 'You are not logged in'

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        session['username'] = request.form['username']
        return redirect(url_for('index'))
    return '''
        <form method="post">
            <p><input type=text name=username>
            <p><input type=submit value=Login>
        </form>
    '''

@app.route('/logout')
def logout():
    # remove the username from the session if it's there
    session.pop('username', None)
    return redirect(url_for('index'))

Comment générer de bonnes clés secrètes

Une clé secrète doit être aussi aléatoire que possible. Votre système d’exploitation a des moyens de générer des données plutôt aléatoires basées sur un générateur aléatoire cryptographique. Utilisez la commande suivante pour générer rapidement une valeur pour Flask.secret_key (ou SECRET_KEY): :

$ python -c 'import os; print(os.urandom(16))'
b'_5#y2L"F4Q8z\n\xec]/'

Une note sur les sessions basées sur les cookies : Flask prendra les valeurs que vous mettez dans l’objet session et les sérialisera dans un cookie. Si vous constatez que certaines valeurs ne persistent pas entre les requêtes, que les cookies sont bien activés et que vous n’obtenez pas de message d’erreur clair, vérifiez la taille du cookie dans les réponses de votre page par rapport à la taille prise en charge par les navigateurs web.

Outre les sessions côté client par défaut, si vous souhaitez gérer les sessions côté serveur, plusieurs extensions Flask le permettent.

Message flash

Les applications et les interfaces utilisateur de qualité reposent sur le retour d’information. Si l’utilisateur n’a pas assez de retour, il finira probablement par détester l’application. Flask fournit un moyen très simple de donner un retour à un utilisateur avec le système de flash. Ce système permet essentiellement d’enregistrer un message à la fin d’une requête et d’y accéder lors de la prochaine requête (et seulement la prochaine). Il est généralement associé à un modèle de mise en page pour exposer le message.

Pour flasher un message, utilisez la méthode flash(), pour obtenir les messages, vous pouvez utiliser get_flashed_messages() qui est également disponible dans les modèles. Voir Message Flashing pour un exemple complet.

Journalisation

Changelog

Nouveau dans la version 0.3.

Parfois, vous pouvez vous trouver dans une situation où vous traitez des données qui devraient être correctes, mais qui ne le sont pas. Par exemple, vous pouvez avoir un code côté client qui envoie une requête HTTP au serveur mais qui est manifestement mal formée. Cela peut être dû à un utilisateur qui modifie les données ou à une défaillance du code client. La plupart du temps, il est normal de répondre par « 400 Bad Request » dans cette situation, mais parfois, cela ne suffit pas et le code doit continuer à fonctionner.

Vous pouvez toujours vouloir enregistrer que quelque chose de louche s’est produit. C’est là que la journalisation est utile. Depuis Flask 0.3, un logger est préconfiguré pour que vous puissiez l’utiliser.

Voici quelques exemples d’appels de journal:

app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')

Le logger attaché est un journal standard Logger, donc allez voir la doc officielle logging pour plus d’informations.

Voir Traitement des erreurs d’application.

Accrochage dans les intergiciels WSGI

Pour ajouter un intergiciel WSGI à votre application Flask, enveloppez l’attribut wsgi_app de l’application. Par exemple, pour appliquer le intergiciel ProxyFix de Werkzeug pour fonctionner derrière Nginx :

from werkzeug.middleware.proxy_fix import ProxyFix
app.wsgi_app = ProxyFix(app.wsgi_app)

Envelopper app.wsgi_app au lieu de app signifie que app pointe toujours vers votre application Flask, et non vers l’intergiciel, donc vous pouvez continuer à utiliser et configurer app directement.

Utiliser les extensions Flask

Les extensions sont des paquets qui vous aident à accomplir des tâches courantes. Par exemple, Flask-SQLAlchemy fournit le support de SQLAlchemy qui rend son utilisation simple et facile avec Flask.

Pour en savoir plus sur les extensions Flask, consultez Extensions.

Déploiement sur un serveur Web

Prêt à déployer votre nouvelle application Flask ? Voir Deployment Options.