Flask入门教程(十四):蓝图(Blueprint)——模块化组织大型项目的利器

发布时间:2026/8/30 15:54:59
Flask入门教程(十四):蓝图(Blueprint)——模块化组织大型项目的利器 1. 为什么需要蓝图蓝图解决的核心问题问题蓝图如何解决代码组织将相关的路由、模板、静态文件归为一组复用性同一个蓝图可以注册到不同应用或注册多次加不同前缀团队协作不同开发者负责不同的蓝图模块减少冲突2. 创建蓝图蓝图使用Blueprint类创建用法和Flask非常相似——同样的路由装饰器、同样的视图函数写法。auth.py用户认证蓝图from flask import Blueprint, render_template, request, session, redirect, url_for # 创建蓝图实例 # 第一个参数 auth 是蓝图的名称用于 url_for 引用 # __name__ 告诉蓝图从哪里查找模板和静态文件 bp Blueprint(auth, __name__) 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))blog.py博客蓝图from flask import Blueprint, render_template bp Blueprint(blog, __name__) bp.route(/) def index(): posts [ {title: Flask 入门, author: runoob}, {title: Blueprint 详解, author: RUNOOB}, ] return render_template(blog/index.html, postsposts) bp.route(/create, methods[GET, POST]) def create(): return render_template(blog/create.html)3. 注册蓝图蓝图创建后不会自动生效需要在应用中注册app.pyfrom 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 # 注册蓝图到应用 # url_prefix为蓝图中所有路由添加统一的前缀 app.register_blueprint(auth_bp, url_prefix/auth) # auth蓝图的路由变成/auth/login, /auth/logout, /auth/register app.register_blueprint(blog_bp) # blog蓝图不带前缀路由保持/、/create注册后的完整路由表URL蓝图endpointurl_for使用/blogblog.index/createblogblog.create/auth/loginauthauth.login/auth/registerauthauth.register/auth/logoutauthauth.logout⚠️注意注册蓝图后url_for()中的endpoint需要加上蓝图名前缀例如url_for(auth.login)而非url_for(login)。4. url_for在蓝图中的使用跨蓝图引用完整endpoint# 在auth蓝图内部引用blog蓝图的视图 blog_url url_for(blog.index) # 跨蓝图引用同蓝图内部引用相对引用# 在auth.py内部使用相对引用更简洁 bp.route(/dashboard) def dashboard(): # 同蓝图内的相对引用以 . 开头 login_url url_for(.login) # 等价于 url_for(auth.login) register_url url_for(.register) # 等价于 url_for(auth.register)url_for()写法实际生成的endpointurl_for(.login)蓝图内部auth.loginurl_for(auth.login)任意位置auth.loginurl_for(blog.index)任意位置blog.index5. 蓝图的模板与静态文件方式一使用蓝图独立模板文件夹不推荐# 创建带有独立模板文件夹的蓝图 bp Blueprint(auth, __name__, template_foldertemplates) # 路径auth/templates/auth/login.html # 渲染时render_template(auth/login.html)方式二统一模板目录推荐最简单的做法是不给蓝图配置独立模板文件夹模板统一放在项目根目录的templates/下用子目录区分myflaskapp/ ├── app.py ├── auth.py ├── blog.py ├── templates/ # 应用级模板统一管理 │ ├── base.html # 公共布局 │ ├── auth/ # auth蓝图的模板 │ │ ├── login.html │ │ └── register.html │ └── blog/ # blog蓝图的模板 │ ├── index.html │ └── create.html └── static/ # 应用级静态文件统一管理 └── style.css查找顺序Flask会先在应用的templates/中查找找不到再去蓝图指定的template_folder文件夹查找。6. 蓝图中的请求钩子蓝图也支持before_request、errorhandler等装饰器用法和app一致bp.before_request def check_login(): 在auth蓝图的所有请求前检查登录状态 # 排除登录和注册页面 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): auth蓝图专用的404错误页面 return render_template(auth/404.html), 404装饰器作用范围说明bp.before_request该蓝图的所有请求请求前执行可提前返回响应bp.after_request该蓝图的所有请求请求后执行可修改响应bp.errorhandler(code)该蓝图的路由仅捕获该蓝图路由中发生的错误7. 工厂模式create_app随着蓝图变多直接在模块顶层创建app Flask(__name__)会遇到循环导入问题。工厂模式是解决这个问题的最佳实践。app.pyfrom flask import Flask def create_app(): 应用工厂函数——返回配置好的Flask实例 app Flask(__name__) app.secret_key dev-secret-key # 加载配置 app.config.from_pyfile(config.py, silentTrue) # 在函数内部导入蓝图避免循环引用 from auth import bp as auth_bp from blog import bp as blog_bp # 注册蓝图 app.register_blueprint(auth_bp, url_prefix/auth) app.register_blueprint(blog_bp) return app工厂模式的优势优势说明消除循环导入蓝图可以导入appapp也可以导入蓝图因为导入发生在函数内部支持测试可以创建不同配置的app实例进行测试多实例部署同一份代码可以创建多个独立的app实例启动工厂模式应用# 方式一通过--app指定工厂函数 flask --app app:create_app() run # 方式二设置环境变量如果使用python-dotenv # .flaskenv中配置FLASK_APPapp:create_app() flask run8. 蓝图最佳实践目录结构推荐的中大型Flask项目目录结构myflaskapp/ ├── app/ # 应用包 │ ├── __init__.py # create_app() 工厂函数 │ ├── config.py # 配置定义 │ ├── models/ # 数据模型 │ │ ├── __init__.py │ │ ├── user.py │ │ └── post.py │ ├── blueprints/ # 蓝图模块 │ │ ├── __init__.py │ │ ├── auth/ # 认证蓝图 │ │ │ ├── __init__.py │ │ │ └── routes.py │ │ └── blog/ # 博客蓝图 │ │ ├── __init__.py │ │ └── routes.py │ ├── templates/ # 模板文件 │ │ ├── base.html │ │ ├── auth/ │ │ └── blog/ │ └── static/ # 静态文件 │ ├── css/ │ └── js/ ├── migrations/ # 数据库迁移 ├── tests/ # 测试代码 ├── .flaskenv # 环境变量 ├── requirements.txt └── run.py # 启动入口可选app/init.py 示例from flask import Flask from flask_sqlalchemy import SQLAlchemy db SQLAlchemy() def create_app(config_classconfig.DevelopmentConfig): app Flask(__name__) app.config.from_object(config_class) # 初始化扩展 db.init_app(app) # 注册蓝图 from app.blueprints.auth import bp as auth_bp from app.blueprints.blog import bp as blog_bp app.register_blueprint(auth_bp, url_prefix/auth) app.register_blueprint(blog_bp) return app9. 蓝图vs普通模块对比对比维度蓝图普通模块无蓝图路由组织bp.route()分组管理全部堆在app.route()URL前缀注册时统一添加url_prefix需在每个路由中手动添加url_for()需加蓝图名前缀auth.login直接使用函数名login模板查找可在蓝图指定template_folder统一使用应用templates/复用性可注册到多个应用不可复用适合规模中大型项目小型项目/学习小结本章全面讲解了Flask的蓝图Blueprint模块化方案。蓝图通过Blueprint类创建使用bp.route()定义路由通过app.register_blueprint()注册到应用并可选url_prefix统一添加前缀url_for()跨蓝图需使用蓝图名.函数名格式同蓝图内可使用相对引用.函数名蓝图支持独立的before_request和errorhandler工厂模式create_app()在函数内部注册蓝图消除循环导入便于测试和配置管理。蓝图是组织大型Flask项目的核心工具建议在项目初期就合理规划蓝图划分。