# 应用工厂与扩展初始化 :::tip 本章概要 Flask 应用工厂模式(`create_app()`)是项目的核心初始化机制。本文详解工厂函数的初始化顺序、扩展注册方式、依赖注入机制,帮助开发者理解应用启动全流程。 ::: ## 应用工厂模式 项目采用 Flask 标准的应用工厂模式,通过 `create_app()` 函数创建和配置应用实例: ```python # src/app.py from flask import Flask from flask_cors import CORS from werkzeug.middleware.proxy_fix import ProxyFix from src.middleware import register_middleware, register_transaction, register_error_handlers, register_operation_log from src.routes.v1 import register_v1 from src.extensions import register_extends from config import DatabaseConfig, REDIS_URL from src.common.utils.json import JSONEncoder def create_app(): """ 创建并配置 Flask 应用实例 配置流程: 1. 创建 Flask 核心对象 2. 配置 Redis 连接 3. 加载数据库配置 4. 设置 JSON 序列化器 5. 配置跨域资源共享 6. 注册操作日志与事务拦截器 7. 注册 API v1 路由 8. 初始化第三方扩展 9. 注册中间件 10. 注入依赖 Returns: Flask: 配置完成的应用实例 """ # 1. 创建 Flask 核心对象 app = Flask(__name__, template_folder='templates', static_folder='../static') # 2. 配置 Redis app.config['REDIS_URL'] = REDIS_URL # 3. 加载数据库配置 app.config.from_object(DatabaseConfig) # 4. 自定义 JSON 序列化器 app.json = JSONEncoder(app) # 5. 配置 CORS CORS(app, resources={r"/*": {"origins": "*"}}, supports_credentials=False) # 6. 注册操作日志 + AOP 事务拦截器 register_operation_log(app) register_transaction(app) # 7. 注册 API v1 路由 register_v1(app) # 8. 初始化扩展(数据库、Redis、调度器等) register_extends(app) # 9. 注册中间件(登录校验、演示模式、异常处理) register_middleware(app) # 10. 注入依赖 _inject_dependencies(app) return app ``` ## 初始化顺序的重要性 初始化顺序经过精心设计,各步骤之间存在依赖关系: ``` Flask 核心对象 ↓ 配置加载(数据库、Redis) ↓ JSON 序列化器 ↓ CORS 跨域 ↓ 操作日志 + 事务拦截器(须在路由之前) ↓ 路由注册(Blueprint 挂载) ↓ 扩展初始化(db.init_app、redis 连接) ↓ 中间件注册(登录校验、演示模式) ↓ 依赖注入(权限提供方、操作日志写入器) ``` :::warning 关键顺序 - `register_operation_log` 必须在 `register_transaction` 之前,确保操作日志在事务提交前记录 - `register_v1`(路由注册)必须在 `register_middleware`(登录校验)之前,否则中间件无法拦截已注册的路由 - `register_extends`(扩展初始化)必须在路由处理请求之前完成 ::: ## 扩展注册(init_app 模式) Flask 扩展采用 `init_app` 模式,将扩展实例与应用绑定: ```python # src/extensions.py from src.core.database import db from src.core.redis_client import redis from src.core.scheduler import scheduler def register_extends(app): """初始化第三方扩展""" # Flask-SQLAlchemy db.init_app(app) # Redis 连接 redis.init_app(app) # APScheduler 定时任务 scheduler.init_app(app) ``` ```python # src/core/database.py from flask_sqlalchemy import SQLAlchemy # 创建扩展实例(不绑定应用) db = SQLAlchemy() ``` 这种模式的优势: 1. **延迟初始化**:扩展实例在模块加载时创建,但绑定应用发生在 `create_app()` 中 2. **测试友好**:测试时可以创建不同的应用实例,扩展自动绑定到测试应用 3. **避免循环导入**:扩展实例定义在 `src/core/`,应用工厂在 `src/app.py`,解耦清晰 ## 路由注册(Blueprint 模式) 所有业务蓝图通过 `src/routes/v1.py` 统一注册到 `/api/v1` 前缀: ```python # src/routes/v1.py from flask import Blueprint from src.modules.system.position.router import position_blue from src.modules.system.user.router import user_blue from src.modules.system.role.router import role_blue # ... 其他模块导入 # 全部业务蓝图(按领域分组排序) BLUEPRINTS = [ # 系统管理模块 user_blue, role_blue, menu_blue, dept_blue, position_blue, level_blue, # 内容管理模块 article_blue, category_blue, link_blue, # 数据管理模块 dict_blue, config_blue, notice_blue, param_blue, city_blue, # 监控管理模块 job_blue, job_log_blue, login_log_blue, operation_log_blue, # 认证模块 auth_blue, # 文件上传 upload_blue, ] def register_v1(app): """ 注册 API v1 路由(所有业务蓝图挂载到 /api/v1) Args: app: Flask 应用实例 """ v1 = Blueprint('v1', __name__, url_prefix='/api/v1') for blue in BLUEPRINTS: v1.register_blueprint(blue) app.register_blueprint(v1) ``` ## 中间件注册 中间件通过 `before_request` / `after_request` / `teardown_request` 钩子实现: ```python # src/middleware/__init__.py from src.middleware.auth import check_login, is_whitelisted, register_middleware from src.middleware.demo import check_demo from src.middleware.transaction import register_transaction, transactional, TransactionContext from src.middleware.operation_log import register_operation_log, operation_log from src.middleware.errors import register_error_handlers ``` 各中间件在 `src/app.py` 的 `create_app()` 中按顺序注册: ```python # src/app.py - create_app() register_operation_log(app) # 操作日志记录 register_transaction(app) # AOP 事务管理 register_v1(app) # 路由注册 register_extends(app) # 扩展初始化 register_middleware(app) # 登录校验 + 白名单 register_error_handlers(app) # 全局异常处理 ``` 中间件执行顺序(请求进入时): ``` 请求进入 ↓ login_required(检查 JWT Token) ↓ check_permission(RBAC 权限校验,装饰器层面) ↓ check_demo(演示模式拦截,装饰器层面) ↓ 路由函数(Router) ↓ Service → Repository → 数据库 ↓ 返回响应 ``` ## 依赖注入 `_inject_dependencies` 将权限查询函数注入到核心模块,解耦业务模块与核心模块: ```python # src/app.py def _inject_dependencies(app): """ 注入依赖(权限提供方 / 操作日志写入器) 通过 app.extensions 字典传递依赖,避免核心模块直接导入业务模块。 """ from src.modules.system.menu.service import get_user_permissions from src.modules.operation_log.service import save_operation_log app.extensions['permission_provider'] = get_user_permissions app.extensions['operation_log_writer'] = save_operation_log ``` ```python # src/core/permission.py from flask import current_app def check_permission(permission: str): """权限校验装饰器""" def decorator(func): @wraps(func) def wrapper(*args, **kwargs): # 通过 current_app 获取注入的权限查询函数 permission_provider = current_app.extensions.get('permission_provider') if permission_provider: user_perms = permission_provider(user_id) if permission not in user_perms: return R.failed(msg="权限不足", code=403) return func(*args, **kwargs) return wrapper return decorator ``` ## 入口文件 ```python # app.py(项目根目录) from src.app import create_app app = create_app() if __name__ == '__main__': app.run(host='0.0.0.0', port=8021, debug=True) ``` 生产环境使用 Gunicorn 启动: ```bash # 4 个工作进程,每个进程 4 个线程 gunicorn -w 4 -t 4 "app:app" --bind 0.0.0.0:8021 ``` ## 总结 项目采用 Flask 标准的应用工厂模式,通过 `create_app()` 按序完成配置加载、扩展初始化、路由注册、中间件注册、依赖注入。扩展采用 `init_app` 模式延迟绑定,路由通过 Blueprint 模块化组织,中间件通过 `before_request` / `after_request` 钩子链式处理。这种设计确保了模块解耦、测试友好、初始化顺序可控。