Blueprint
Lorsque l'application ne comporte qu'un seul fichier, écrire toutes les routes ensemble ne pose pas de problème.
Mais à mesure que les fonctionnalités se développent—module utilisateur, module article, backend d'administration—le code devient difficile à maintenir.
BlueprintC'est la solution modulaire fournie par Flask, qui vous permet de diviser l'application en unités fonctionnelles indépendantes.
Pourquoi les blueprints sont nécessaires
Le problème central que les blueprints résolvent :
- Organisation du codeRegrouper les routes, les modèles et les fichiers statiques associés
- RéutilisabilitéLe même blueprint peut être enregistré sur différentes applications, ou enregistré plusieurs fois (avec différents préfixes)
- Collaboration d'équipe: Différents développeurs sont responsables de différents modules de blueprint, ce qui réduit les conflits.
Création d'un blueprint
Utilisation d'un blueprintBlueprintCréation de classe, utilisation etFlaskTrès similaire—les mêmes décorateurs de route, la même syntaxe de fonction de vue :
Exemple
from flask import Blueprint, render_template, request, session, redirect, url_for
# Créer une instance de blueprint
# Le premier paramètre "auth" est le nom du blueprint (utilisé pour les références url_for)
# __name__ indique au blueprint où trouver les templates et les fichiers statiques
bp = Blueprint("auth", __name__)
# Utilisez bp.route dans le blueprint, et non app.route
@bp.route("/login", methods=["GET", "POST"])
def login():
if request.method == "POST":
username = request.form.get("username", "")
if username:
session["username"] = username
return redirect(url_for("blog.index"))
return render_template("auth/login.html")
@bp.route("/register", methods=["GET", "POST"])
def register():
if request.method == "POST":
username = request.form.get("username", "")
if username:
return redirect(url_for("auth.login"))
return render_template("auth/register.html")
@bp.route("/logout")
def logout():
session.clear()
return redirect(url_for("blog.index"))
Exemple
from flask import Blueprint, render_template
bp = Blueprint("blog", __name__)
@bp.route("/")
def index():
# Données d'articles fictives
posts = [
{"title": Introduction à Flask, "author": "exemple"},
{"title": Explication des blueprints, "author": "EXEMPLE"},
]
return render_template("blog/index.html", posts=posts)
@bp.route("/create", methods=["GET", "POST"])
def create():
return render_template("blog/create.html")
Enregistrement du Blueprint
Un Blueprint ne prend pas effet automatiquement après sa création ; il doit être enregistré dans l'application :
Exemple
from flask import Flask
from auth import bp as auth_bp
from blog import bp as blog_bp
app = Flask(__name__)
app.secret_key = "dev-secret-key"
# Enregistrer le Blueprint avec l'application
# url_prefix : ajoute un préfixe commun à toutes les routes du Blueprint
app.register_blueprint(auth_bp, url_prefix="/auth")
# Les routes du Blueprint auth deviennent : /auth/login, /auth/logout, /auth/register
app.register_blueprint(blog_bp)
# Le Blueprint blog n'a pas de préfixe, les routes restent : /, /create
Table complète des routes après enregistrement :
| URL | Blueprint | point de terminaison (utilisé par url_for) |
|---|---|---|
| / | blog | blog.index |
| /create | blog | blog.create |
| /auth/login | auth | auth.login |
| /auth/register | auth | auth.register |
| /auth/logout | auth | auth.logout |
Après avoir enregistré le blueprint,url_for()Dans celui-ci, le point de terminaison doit avoir le nom du blueprint ajouté comme préfixe, par exempleurl_for("auth.login")plutôt queurl_for("login")。
Utilisation spéciale de url_for dans les blueprints
Au sein du même blueprint, vous pouvez utiliser des références relatives qui commencent par un point :
Exemple
@bp.route("/")
def index():
# Références relatives au sein du même blueprint (commençant par un point)
login_url = url_for(".login") # Équivalent à url_for("auth.login")
register_url = url_for(".register") # Équivalent à url_for("auth.register")
# Le référencement entre blueprints nécessite le point de terminaison complet
blog_url = url_for("blog.index") # Référence l'index du blueprint blog
Modèles et fichiers statiques des blueprints
Les blueprints peuvent également avoir leurs propres modèles et fichiers statiques.
Lorsqu'un blueprint possède son propre dossier de templates, Flask va d'abord chercher dans lestemplatesde l'application, y chercher, et s'il n'est pas trouvé, chercher dans le dossier spécifié par le blueprint.
Exemple
bp = Blueprint("auth", __name__, template_folder="templates")
# Organisation des templates spécifique au blueprint
# Chemin : auth/templates/auth/login.html
# Lors du rendu : render_template("auth/login.html")
# Cette organisation évite les conflits de noms de fichiers (login.html peut différer entre auth et blog)
Structure de répertoires recommandée pour le blueprint :
myflaskapp/
├── app.py # 应用入口,注册蓝图
├── auth.py # 认证蓝图
├── blog.py # 博客蓝图
├── templates/ # 应用级模板(公共 base.html 等)
│ └── base.html
├── static/ # 应用级静态文件
│ └── style.css
├── auth/ # auth 蓝图的独立资源(可选)
│ └── templates/
│ └── auth/
│ ├── login.html
│ └── register.html
└── blog/ # blog 蓝图的独立资源(可选)
└── templates/
└── blog/
├── index.html
└── create.html
L'approche la plus simple consiste à ne pas configurer de dossier de templates séparé pour le blueprint, et à placer les templates uniformément dans letemplates/du répertoire racine du projet. Ci-dessous, distinguez par sous-répertoires :templates/auth/login.html、templates/blog/index.html。
Modèle d'usine — create_app
À mesure que les blueprints se multiplient, le fait de les créer directement au niveau supérieur du moduleapp = Flask(__name__)rencontrera des problèmes d'importation circulaire.
Le pattern Factory est la meilleure pratique pour résoudre ce problème :
Exemple
from flask import Flask
def create_app():
"""Fonction factory d'application — renvoie une instance Flask configurée"""
app = Flask(__name__)
app.secret_key = "dev-secret-key"
# Charger la configuration
app.config.from_pyfile("config.py", silent=True)
# Importer les blueprints à l'intérieur de la fonction pour éviter les imports circulaires
from auth import bp as auth_bp
from blog import bp as blog_bp
# Enregistrer le blueprint
app.register_blueprint(auth_bp, url_prefix="/auth")
app.register_blueprint(blog_bp)
return app
Avantages du pattern Factory :
- Éliminer les imports circulairesLes blueprints peuvent être importésapp,appVous pouvez aussi importer des blueprints, car l'import se produit à l'intérieur de la fonction.
- Prise en charge des testsPermet de créer des instances d'application avec différentes configurations pour les tests
- Déploiement multi-instancesLe même code peut créer plusieurs instances d'application indépendantes
Après avoir utilisé le pattern Factory, vous devezflask --app "app:create_app()" runDémarrer :
$ flask --app "app:create_app()" run
Autres fonctionnalités des blueprints
Les blueprints prennent également en charge des décorateurs tels que before_request, errorhandler, etc., et leur utilisation est identique à celle de l'app :
Exemple
def check_login():
"""Vérifier l'état de connexion avant toutes les requêtes dans le blueprint d'authentification"""
if request.endpoint not in ("auth.login", "auth.register"):
if "username" not in session:
return redirect(url_for("auth.login"))
@bp.errorhandler(404)
def not_found(error):
"""Page d'erreur 404 dédiée au blueprint d'authentification"""
return render_template("auth/404.html"), 404
autres extensionsLebefore_request du BlueprintIl n'affecte que les routes à l'intérieur de ce blueprint. Si vous devez exécuter une logique avant toutes les requêtes, vous devez utiliserapp.before_request。