:中间件与扩展——增强应用功能的两种机制)
1. Flask中间件Flask的中间件是对请求和响应进行处理的钩子通常用于在请求到达视图函数之前或在响应发送到客户端之前执行一些操作。中间件可以用于日志记录、请求修改、响应修改、性能监控等。1.1 请求钩子推荐方式请求钩子允许你在处理请求的不同阶段插入代码Flask提供了四种钩子装饰器触发时机典型用途app.before_request每个请求处理之前权限验证、数据库连接、请求日志app.after_request每个请求处理之后响应返回之前添加响应头、压缩响应内容app.teardown_request请求结束后无论是否发生异常释放资源、关闭数据库连接app.before_first_request应用第一次处理请求之前仅执行一次初始化全局资源、预热缓存app.pyfrom flask import Flask, request app Flask(__name__) app.before_request def before_request(): print(Before request) # 可以在这里做权限检查如果未认证可提前返回响应 # if not session.get(user): # return redirect(/login) app.after_request def after_request(response): print(After request) # 添加自定义响应头 response.headers[X-Request-Time] 123ms return response app.teardown_request def teardown_request(exception): print(Teardown request) # 清理资源如关闭数据库连接 # 如果有异常exception参数包含异常对象 app.before_first_request def before_first_request(): print(第一次请求前执行仅一次) app.route(/) def index(): return Hello, World!多个钩子的执行顺序请求到达 │ ▼ app.before_first_request仅第一次请求执行 │ ▼ app.before_request按注册顺序执行 │ ▼ 路由匹配 → 视图函数执行 │ ▼ app.after_request按注册逆序执行 │ ▼ 响应返回客户端 │ ▼ app.teardown_request异常时也执行1.2 蓝图中的请求钩子蓝图也支持独立的请求钩子只作用于该蓝图的路由# auth.py from flask import Blueprint bp Blueprint(auth, __name__) bp.before_request def check_auth(): 只对auth蓝图的路由生效 if request.endpoint not in (auth.login, auth.register): if username not in session: return redirect(url_for(auth.login))1.3 自定义WSGI中间件除了请求钩子Flask还允许你创建自定义WSGI中间件类在更底层对请求和响应进行操作。middleware.pyclass CustomMiddleware: def __init__(self, app): self.app app def __call__(self, environ, start_response): def custom_start_response(status, headers): # 在响应头中添加自定义字段 headers.append((X-Custom-Header, Value)) return start_response(status, headers) # 可以在这里修改请求环境environ # environ[REMOTE_USER] custom_user return self.app(environ, custom_start_response)app.pyfrom flask import Flask from middleware import CustomMiddleware app Flask(__name__) # 将自定义中间件包装到wsgi_app上 app.wsgi_app CustomMiddleware(app.wsgi_app) app.route(/) def index(): return Hello, World!请求钩子比自定义WSGI中间件更简单、更符合Flask风格优先推荐使用请求钩子。只有当需要修改WSGI底层环境如environ时才考虑自定义中间件。2. Flask扩展Flask扩展是用于为Flask应用添加功能的插件可以集成第三方库提供例如数据库集成、表单处理、用户认证等功能。2.1 常见的Flask扩展扩展功能安装命令Flask-SQLAlchemy数据库ORM集成pip install flask-sqlalchemyFlask-WTF表单处理与验证pip install flask-wtfFlask-Login用户会话管理与认证pip install flask-loginFlask-Migrate数据库迁移管理pip install flask-migrateFlask-Mail发送电子邮件pip install flask-mailFlask-CORS跨域资源共享pip install flask-corsFlask-Caching缓存支持pip install flask-cachingFlask-RESTfulRESTful API开发pip install flask-restfulFlask-SocketIOWebSocket实时通信pip install flask-socketioFlask-Admin管理后台快速搭建pip install flask-admin2.2 安装和使用Flask扩展以Flask-SQLAlchemy为例pip install flask-sqlalchemyapp.pyfrom flask import Flask from flask_sqlalchemy import SQLAlchemy app Flask(__name__) app.config[SQLALCHEMY_DATABASE_URI] sqlite:///example.db db SQLAlchemy(app) class User(db.Model): id db.Column(db.Integer, primary_keyTrue) username db.Column(db.String(80), uniqueTrue, nullableFalse) app.route(/) def index(): return Hello, World!2.3 延迟初始化模式在工厂模式create_app中扩展通常采用延迟初始化from flask import Flask from flask_sqlalchemy import SQLAlchemy # 先创建扩展实例不绑定应用 db SQLAlchemy() def create_app(): app Flask(__name__) app.config[SQLALCHEMY_DATABASE_URI] sqlite:///example.db # 在工厂函数中绑定应用 db.init_app(app) return app3. 创建自定义扩展如果现有的扩展不能满足你的需求你可以创建自己的扩展。3.1 简单自定义扩展myextension.pyclass MyExtension: def __init__(self, appNone): self.app app if app is not None: self.init_app(app) def init_app(self, app): app.config.setdefault(MY_EXTENSION_CONFIG, default_value) app.after_request(self.after_request) def after_request(self, response): response.headers[X-My-Extension] MyValue return responseapp.pyfrom flask import Flask from myextension import MyExtension app Flask(__name__) my_ext MyExtension(app) app.route(/) def index(): return Hello, World!3.2 支持配置的自定义扩展class MyExtension: def __init__(self, appNone): if app is not None: self.init_app(app) def init_app(self, app): # 设置默认配置用户可通过app.config覆盖 app.config.setdefault(MY_EXTENSION_ENABLED, True) app.config.setdefault(MY_EXTENSION_TIMEOUT, 30) # 注册请求钩子 app.before_request(self.before_request) # 将扩展实例挂载到app上方便其他地方使用 app.my_extension self def before_request(self): 在请求前执行的操作 pass4. 中间件vs扩展对比对比维度中间件请求钩子扩展用途请求/响应处理、日志、权限验证集成第三方库、添加新功能实现方式app.before_request等装饰器Python类 init_app()作用范围全局或蓝图级别全局按需注册复杂度简单从简单到复杂不等典型场景请求日志、响应头添加、权限检查数据库、表单、认证、缓存5. 常用扩展配置速查扩展初始化方式关键配置Flask-SQLAlchemydb SQLAlchemy(app)SQLALCHEMY_DATABASE_URIFlask-WTFapp.secret_key ...WTF_CSRF_ENABLEDFlask-Loginlogin_manager.init_app(app)LOGIN_VIEWFlask-Migratemigrate Migrate(app, db)无Flask-Mailmail Mail(app)MAIL_SERVER,MAIL_PORTFlask-CORSCORS(app)CORS_ORIGINS小结本章全面讲解了Flask的中间件与扩展机制。中间件方面请求钩子before_request、after_request、teardown_request、before_first_request是处理请求前后逻辑的推荐方式蓝图也支持独立的钩子自定义WSGI中间件通过包装app.wsgi_app实现更底层的控制。扩展方面Flask拥有丰富的扩展生态SQLAlchemy、WTF、Login、Migrate等通过pip install安装后使用扩展类(app)或扩展类().init_app(app)方式集成自定义扩展可封装可复用的功能。合理使用中间件和扩展能大大增强Flask应用的功能和可维护。