1. Flask中间件
Flask的中间件是对请求和响应进行处理的钩子,通常用于在请求到达视图函数之前或在响应发送到客户端之前执行一些操作。中间件可以用于日志记录、请求修改、响应修改、性能监控等。
1.1 请求钩子(推荐方式)
请求钩子允许你在处理请求的不同阶段插入代码,Flask提供了四种钩子:
| 装饰器 | 触发时机 | 典型用途 |
|---|---|---|
@app.before_request |
每个请求处理之前 | 权限验证、数据库连接、请求日志 |
@app.after_request |
每个请求处理之后,响应返回之前 | 添加响应头、压缩响应内容 |
@app.teardown_request |
请求结束后(无论是否发生异常) | 释放资源、关闭数据库连接 |
@app.before_first_request |
应用第一次处理请求之前(仅执行一次) | 初始化全局资源、预热缓存 |
from 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中间件类,在更底层对请求和响应进行操作。
class 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)
from 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-sqlalchemy |
| Flask-WTF | 表单处理与验证 | pip install flask-wtf |
| Flask-Login | 用户会话管理与认证 | pip install flask-login |
| Flask-Migrate | 数据库迁移管理 | pip install flask-migrate |
| Flask-Mail | 发送电子邮件 | pip install flask-mail |
| Flask-CORS | 跨域资源共享 | pip install flask-cors |
| Flask-Caching | 缓存支持 | pip install flask-caching |
| Flask-RESTful | RESTful API开发 | pip install flask-restful |
| Flask-SocketIO | WebSocket实时通信 | pip install flask-socketio |
| Flask-Admin | 管理后台快速搭建 | pip install flask-admin |
2.2 安装和使用Flask扩展
以Flask-SQLAlchemy为例:
pip install flask-sqlalchemy
from 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_key=True) username = db.Column(db.String(80), unique=True, nullable=False) @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 app
3. 创建自定义扩展
如果现有的扩展不能满足你的需求,你可以创建自己的扩展。
3.1 简单自定义扩展
class MyExtension: def __init__(self, app=None): 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 response
from 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, app=None): 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): """在请求前执行的操作""" pass
4. 中间件vs扩展对比
| 对比维度 | 中间件(请求钩子) | 扩展 |
|---|---|---|
| 用途 | 请求/响应处理、日志、权限验证 | 集成第三方库、添加新功能 |
| 实现方式 | @app.before_request等装饰器 |
Python类 + init_app() |
| 作用范围 | 全局或蓝图级别 | 全局,按需注册 |
| 复杂度 | 简单 | 从简单到复杂不等 |
| 典型场景 | 请求日志、响应头添加、权限检查 | 数据库、表单、认证、缓存 |
5. 常用扩展配置速查
| 扩展 | 初始化方式 | 关键配置 |
|---|---|---|
| Flask-SQLAlchemy | db = SQLAlchemy(app) |
SQLALCHEMY_DATABASE_URI |
| Flask-WTF | app.secret_key = '...' |
WTF_CSRF_ENABLED |
| Flask-Login | login_manager.init_app(app) |
LOGIN_VIEW |
| Flask-Migrate | migrate = Migrate(app, db) |
无 |
| Flask-Mail | mail = Mail(app) |
MAIL_SERVER, MAIL_PORT |
| Flask-CORS | CORS(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应用的功能和可维护。