Middleware et intergiciels Flask

Dans Flask, les middlewares et les extensions sont deux mécanismes clés pour améliorer et étendre les fonctionnalités d'une application.

Grâce aux middlewares et aux extensions, vous pouvez considérablement améliorer les fonctionnalités et la flexibilité des applications Flask, ce qui leur permet de répondre à diverses exigences complexes.

La suite détaille les concepts des deux et comment les utiliser.

Middleware Flask:

  • Utilisez des hooks de requête pour insérer du code à différentes étapes du traitement des requêtes.
  • Créez des classes de middleware personnalisées pour gérer les requêtes et les réponses.

Extensions Flask:

  • Utilisez des extensions existantes (telles que Flask-SQLAlchemy, Flask-WTF) pour ajouter des fonctionnalités.
  • Créer des extensions personnalisées pour répondre à des besoins spécifiques.

1. Middleware Flask

Le middleware Flask est un hook pour traiter les requêtes et les réponses, généralement utilisé pour effectuer des opérations avant que les requêtes n'atteignent les fonctions de vue ou avant que les réponses ne soient envoyées aux clients. Le middleware peut être utilisé pour la journalisation, la modification de requête, la modification de réponse, et plus encore.

1.1 Hooks de requête

Les hooks de requête vous permettent d'insérer du code à différentes étapes du traitement des requêtes. Flask fournit plusieurs hooks pour gérer différentes étapes du cycle de vie des requêtes :

  • before_request: Exécuté avant que chaque requête ne soit traitée.
  • after_request: Exécuté après le traitement de chaque requête.
  • teardown_request: Exécuté après la fin du traitement de la requête, qu'une exception se produise ou non.
  • before_first_request: Exécuté uniquement avant que l'application ne traite la première requête.

Code du fichier app.py :

Exemple

from flask import Flask, request

app = Flask(__name__)

@app.before_request
def before_request():
    print('Before request')

@app.after_request
def after_request(response):
    print('After request')
    return response

@app.teardown_request
def teardown_request(exception):
    print('Teardown request')

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

if __name__ == '__main__':
    app.run(debug=True)
  • @app.before_request: Afficher "Before request" avant que chaque requête soit traitée.
  • @app.after_request: Afficher "After request" après que chaque requête soit traitée.
  • @app.teardown_request: Afficher "Teardown request" après que chaque requête soit traitée, qu'une exception se produise ou non.

1.2 Middleware personnalisé

Flask vous permet également de créer des classes de middleware personnalisées, qui peuvent intervenir à différentes étapes du traitement des requêtes et des réponses.

Code du fichier middleware.py :

Exemple

class CustomMiddleware:
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        def custom_start_response(status, headers):
            headers.append(('X-Custom-Header', 'Value'))
            return start_response(status, headers)

        return self.app(environ, custom_start_response)

Code du fichier app.py :

Exemple

from flask import Flask
from middleware import CustomMiddleware

app = Flask(__name__)

app.wsgi_app = CustomMiddleware(app.wsgi_app)

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

if __name__ == '__main__':
    app.run(debug=True)

CustomMiddleware: classe de middleware personnalisée qui ajoute un en-tête de réponse personnalisé.

2. Extensions Flask

Les extensions Flask sont des plugins utilisés pour ajouter des fonctionnalités aux applications Flask. Les extensions Flask peuvent intégrer des bibliothèques tierces, en fournissant des fonctionnalités telles que l'intégration de bases de données, le traitement de formulaires, l'authentification des utilisateurs, et plus encore.

2.1 Extensions Flask courantes

  • Flask-SQLAlchemy: Intègre l'ORM SQLAlchemy, ce qui rend les opérations sur la base de données plus pratiques.
  • Flask-WTF: Intègre la bibliothèque de formulaires WTForms, ce qui simplifie le traitement des formulaires.
  • Flask-Login: Fournit la gestion des sessions utilisateur et des fonctionnalités d'authentification des utilisateurs.
  • Flask-Migrate: Une extension pour les migrations de base de données, basée sur Alembic.
  • Flask-Mail: Sert à envoyer des e-mails.

2.2 Installation et utilisation des extensions Flask

En prenant Flask-SQLAlchemy comme exemple, installation :

pip install flask-sqlalchemy

Configuration et utilisation, code du fichier app.py :

Exemple

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///example.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)

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

if __name__ == '__main__':
    app.run(debug=True)

L'extension SQLAlchemy intègre SQLAlchemy, ce qui vous permet de définir facilement des modèles et d'interagir avec la base de données.

2.3 Création d'extensions personnalisées

Si les extensions existantes ne répondent pas à vos besoins, vous pouvez créer votre propre extension. La création d'une extension personnalisée implique généralement de définir une classe qui fournit une configuration d'initialisation et des fonctionnalités associées.

code du fichier myextension.py :

Exemple

class MyExtension:
    def __init__(self, app=None):
        if app is not None:
            self.init_app(app)

    def init_app(self, app):
        app.config.setdefault('MY_EXTENSION_CONFIG', 'default_value')
        app.after_request(self.after_request)

    def after_request(self, response):
        response.headers['X-My-Extension'] = 'MyValue'
        return response

Code du fichier app.py :

Exemple

from flask import Flask
from myextension import MyExtension

app = Flask(__name__)
my_ext = MyExtension(app)

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

if __name__ == '__main__':
    app.run(debug=True)

MyExtension: Extension personnalisée qui ajoute un en-tête de réponse personnalisé.

autres extensions