工厂函数
1. 为什么要有create_app这个函数?
在传统的单文件写法中,我们会直接写app = Flask(__name__)。但在企业级项目中,这有一个致命问题:配置(Config)和 扩展(Extensions)必须在 app 创建后才能初始化,但很多模块又需要用到 app。这就导致了“先有鸡还是先有蛋”的矛盾。
create_app这个工厂函数完美解决了这个问题:
- 延迟初始化:先创建 app 骨架。
- 按需加载配置:比如测试环境传入
'test',生产环境传入'prod',同一个工厂函数能生产出不同配置的实例。 - 解决循环导入:在函数内部导入蓝图,避免模块之间的依赖死锁。
2. 如何在__init__.py中完善这个工程函数?
在企业开发中,一个成熟的__init__.py通常还会包含以下几个部分。我们可以把你的代码进行升级:
# app/__init__.pyfromflaskimportFlaskfromapp.configimportConfig# 假设这里可能有多个配置类,比如 TestConfig, DevConfig# 1. 实例化扩展(这里先不传 app,避免循环引用)# from flask_sqlalchemy import SQLAlchemy# db = SQLAlchemy()defcreate_app(config_class=Config):"""应用工厂函数"""# 2. 创建 Flask 实例app=Flask(__name__)# 3. 加载配置app.config.from_object(config_class)# 4. 初始化扩展(在 app 创建后,在这里进行初始化)# db.init_app(app)# 5. 注册蓝图(必须在函数内部 import,防止循环导入)fromapp.routes.mainimportmain_bpfromapp.routes.userimportuser_bp app.register_blueprint(main_bp)# 首页路由app.register_blueprint(user_bp)# 用户路由returnapp3. 有了这个工厂函数,启动文件(run.py)怎么写?
有了__init__.py里的工厂函数,你的项目根目录的启动文件就会变得极其干净和灵活:
# run.py (或者在更规范的写法中是 manage.py 配合 Flask-Script/Click)fromappimportcreate_app# 假设你想跑一个测试环境,或者从环境变量读取app=create_app()if__name__=='__main__':app.run(debug=True)