create_app()必须是函数而非全局变量,否则会导致测试实例污染、多环境配置硬编码、蓝图循环导入三类硬伤;其核心是延迟初始化:先创建空app,再按需加载配置、init_app扩展、注册蓝图、确保instance_path。

Flask工厂模式不是“可选技巧”,而是大型应用的启动门槛——没它,多环境部署、单元测试、蓝图解耦全会卡在导入阶段。
为什么create_app()必须是函数,不能是全局变量
直接写 app = Flask(__name__) 会导致三类硬伤:
- 测试时无法为每个用例新建干净实例,数据库连接、扩展状态会互相污染
- 开发/生产配置只能靠改代码或环境变量硬编码,CI/CD 流水线没法自动切换
- 蓝图里如果要
from app import db,而app.py又要from views import xxx,立刻触发循环导入
工厂函数把「创建」和「配置」拆开:先有空壳 app,再按需塞配置、注册扩展、挂蓝图。所有依赖都延迟到 create_app() 被调用那一刻才初始化。
create_app() 函数里必须做的四件事
一个可用的工厂函数不是只返回 app 就完事。漏掉任何一项,后续模块就容易出隐性故障:
-
加载配置:用
app.config.from_object(Config)或app.config.from_pyfile("config.py"),别手写app.config["KEY"] = value -
初始化扩展:如
db.init_app(app)、login_manager.init_app(app)—— 必须用init_app(),不能直接db = SQLAlchemy(app) -
注册蓝图:用
app.register_blueprint(auth_bp, url_prefix="/auth"),避免在蓝图内部反向导入app -
确保实例路径存在:
os.makedirs(app.instance_path, exist_ok=True),否则写日志、上传文件时可能报FileNotFoundError
示例片段(非完整):
def create_app(config_name="development"):
app = Flask(__name__)
app.config.from_object(config_by_name[config_name])
db.init_app(app)
login_manager.init_app(app)
from app.auth import auth_bp
app.register_blueprint(auth_bp, url_prefix="/auth")
os.makedirs(app.instance_path, exist_ok=True)
return app
蓝图注册时最容易踩的三个坑
注册蓝图看着简单,但实际项目里 70% 的 404 或路由冲突都出在这一步:
-
延迟导入必须做:蓝图模块(如
auth.py)不能在模块顶层就访问app或db,所有依赖都要放在函数内或用@bp.before_app_request钩子处理 -
url_prefix别漏斜杠:写成url_prefix="/auth"是对的,url_prefix="auth"会导致所有路由变成/authlogin这种拼接错误 -
模板路径以蓝图名为根:如果
Blueprint("auth", __name__, template_folder="templates"),那render_template("login.html")会找templates/login.html,不是templates/auth/login.html;要后者得显式写template_folder="templates/auth"
配置类怎么组织才不翻车
用类继承比字典 or 环境变量拼接更可控,尤其当配置项开始带逻辑判断时:
- 基类
Config放通用项(如SECRET_KEY),子类只覆盖差异项(如DATABASE_URI) - 开发环境用
sqlite:///dev.db,测试环境强制用sqlite:///:memory:,生产环境必须从os.getenv("DATABASE_URL")读取 - 别把敏感配置写死在代码里:生产环境的
SECRET_KEY应该由部署工具注入,代码里只设默认值用于本地调试
关键点:工厂函数接收的 test_config 参数,就是给单元测试留的后门——测试时传入 TestConfig 类,完全绕过配置文件读取逻辑。
真正难的不是写出 create_app(),而是让所有团队成员都习惯「不碰全局 app」「蓝图不依赖 app 实例」「配置不写死」——这些约束一旦松动,整个架构就退化回单文件泥潭。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











