Flask 教程

Flask 中间件和扩展

在 Flask 中,中间件(Middleware)扩展(Extensions)是增强应用功能的两大支柱。

  • 中间件:像“过滤器”或“拦截器”,在请求到达视图函数之前或响应返回给客户端之后执行通用逻辑(如日志、认证、CORS)。
  • 扩展:像“插件”,为 Flask 添加特定的重型功能(如数据库 ORM、用户登录管理、表单验证)。

一、 Flask 中间件 (Middleware)

Flask 基于 Werkzeug WSGI 工具包,因此它的中间件机制遵循标准的 WSGI 规范。你可以通过两种方式实现中间件:

1. 使用 @app.before_request@app.after_request (最常用)

这是 Flask 内置的“轻量级中间件”机制,适合处理与请求/响应直接相关的逻辑。

纯文本
plaintext
from flask import Flask, request, g
import time

app = Flask(__name__)

# 1. 请求前执行 (Before Request)
@app.before_request
def before_req():
    # 记录请求开始时间
    g.start_time = time.time()
    print(f"Request started: {request.method} {request.path}")

# 2. 请求后执行 (After Request)
@app.after_request
def after_req(response):
    # 计算耗时并添加到响应头
    duration = time.time() - g.start_time
    response.headers['X-Response-Time'] = f"{duration:.4f}s"
    print(f"Request finished with status: {response.status_code}")
    return response  # 必须返回 response 对象

2. 使用 WSGI 中间件类 (高级/全局)

如果你需要介入更底层的 WSGI 流程(例如在所有 Flask 逻辑之前修改环境),可以编写一个标准的 WSGI 中间件类,并将其包装在 app.wsgi_app 上。

纯文本
plaintext
class MyCustomMiddleware:
    def __init__(self, app):
        self.app = app

    def __call__(self, environ, start_response):
        # 在这里可以修改 environ 字典
        environ['MY_CUSTOM_VAR'] = 'Hello from Middleware'

        # 调用下一个应用(即 Flask app)
        return self.app(environ, start_response)

# 注册中间件
app.wsgi_app = MyCustomMiddleware(app.wsgi_app)

3. 常见中间件场景

  • CORS (跨域资源共享):允许前端不同域名访问 API。
  • Compression: 自动压缩响应内容(Gzip)。
  • Logging: 记录所有请求的详细日志。
  • Authentication: 检查 Header 中的 Token。

二、 Flask 扩展 (Extensions)

Flask 核心非常精简,复杂功能都通过扩展实现。扩展通常以 Flask- 开头命名。

🏆 必装的“四大金刚”扩展

扩展名用途安装命令
Flask-SQLAlchemy数据库 ORM (操作 MySQL/PostgreSQL/SQLite)pip install flask-sqlalchemy
Flask-Migrate数据库版本管理 (基于 Alembic)pip install flask-migrate
Flask-WTF表单处理与 CSRF 保护pip install flask-wtf
Flask-Login用户会话管理 (登录/登出/记住我)pip install flask-login

其他常用扩展

  • Flask-CORS: 处理跨域问题 (pip install flask-cors)
  • Flask-Mail: 发送邮件 (pip install flask-mail)
  • Flask-RESTful / Flask-Marshmallow: 构建 REST API
  • Flask-Caching: 缓存支持 (Redis/Memcached)
  • Flask-JWT-Extended: JSON Web Token 认证 (适合前后端分离/API)

三、 如何正确初始化扩展?(应用工厂模式)

在大型项目中,为了避免循环导入并支持测试,我们使用应用工厂模式。扩展的初始化分为两步:实例化绑定

1. 定义扩展实例 (extensions.py)

只创建对象,不绑定 app。

纯文本
plaintext
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_login import LoginManager

db = SQLAlchemy()
migrate = Migrate()
login_manager = LoginManager()

2. 在工厂中初始化 (app/__init__.py)

纯文本
plaintext
from flask import Flask
from .extensions import db, migrate, login_manager

def create_app():
    app = Flask(__name__)
    app.config.from_object('config.Config')

    # ⚠️ 关键步骤:调用 init_app 将扩展绑定到当前 app
    db.init_app(app)
    migrate.init_app(app, db)
    login_manager.init_app(app)

    # 配置 Login Manager
    login_manager.login_view = 'auth.login'

    # 注册蓝图...

    return app

四、 实战示例:集成 Flask-CORS 和 Flask-Login

1. 解决跨域 (Flask-CORS)

如果你的前端运行在 localhost:3000,后端在 localhost:5000,浏览器会阻止请求。

纯文本
plaintext
pip install flask-cors
纯文本
plaintext
from flask_cors import CORS

def create_app():
    app = Flask(__name__)

    # 简单用法:允许所有域 (开发环境方便,生产环境需限制)
    CORS(app) 

    # 高级用法:只允许特定域
    # CORS(app, resources={r"/api/*": {"origins": "https://myfrontend.com"}})

    return app

2. 用户登录保护 (Flask-Login)

保护某些路由只有登录用户才能访问。

纯文本
plaintext
pip install flask-login
纯文本
plaintext
from flask_login import LoginManager, login_user, logout_user, login_required, current_user

login_manager = LoginManager()

# 加载用户的回调函数
@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

@app.route('/dashboard')
@login_required  # ⭐ 装饰器:如果未登录,自动重定向到登录页
def dashboard():
    return f'Hello, {current_user.username}'

@app.route('/login', methods=['POST'])
def login():
    user = User.query.filter_by(username=request.form['username']).first()
    if user and check_password_hash(user.password, request.form['password']):
        login_user(user) # 建立会话
        return redirect(url_for('dashboard'))
    return 'Login failed', 401

💡 最佳实践建议

  1. 不要重复造轮子:在写复杂功能(如发邮件、连数据库、做认证)前,先搜一下有没有成熟的 Flask 扩展。
  2. 按需引入:Flask 的优势是轻量。如果只是一个简单的内部工具,可能只需要 Flask-SQLAlchemy,不需要引入沉重的 Flask-AdminCelery
  3. 注意扩展兼容性:某些扩展可能不再维护。优先选择社区活跃、文档齐全、最近一年有更新的扩展。
  4. 中间件顺序:如果有多个 WSGI 中间件,注意它们的包裹顺序。内层的中间件先执行。

📝 总结

  • 小逻辑、请求级处理 → 用 @before_request / @after_request
  • 底层拦截、全局修改 → 用 WSGI 中间件类。
  • 重型功能(DB, Auth, Form) → 用 Flask 扩展。
  • 初始化扩展 → 记得在应用工厂中使用 init_app(app)

掌握了中间件和扩展,你就拥有了组装强大 Flask 应用的“乐高积木”。接下来,你想深入了解某个具体扩展(如 SQLAlchemy 高级查询JWT 认证),还是学习如何部署你的应用?

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注