Flask 中的 装饰器(Decorator) 和 上下文管理器(Context Manager) 都用于增强代码的功能,但它们的用途和实现方式不同。
1. 装饰器(Decorator)
特点
✅ 用于修改或增强函数/类的行为,不影响原始代码。
✅ 常用于 Flask 的路由、请求前后处理、认证等。
✅ 基于 Python 的高阶函数,使用 @
语法。
示例
python">from flask import Flaskapp = Flask(__name__)# Flask 路由装饰器
@app.route('/')
def home():return "Hello, Flask!"
这里 @app.route('/')
是一个装饰器,它修改了 home()
的行为,使其成为 Flask 的路由处理函数。
应用场景
- 定义 URL 路由(
@app.route
)。 - 请求前后钩子(
@app.before_request
,@app.after_request
)。 - 自定义权限认证(
@login_required
)。 - 错误处理(
@app.errorhandler(404)
)。
自定义 Flask 装饰器
python">from flask import request, jsonifydef login_required(f):def wrapper(*args, **kwargs):token = request.headers.get("Authorization")if not token:return jsonify({"error": "未授权"}), 401return f(*args, **kwargs)return wrapper@app.route('/protected')
@login_required
def protected():return jsonify({"message": "成功访问受保护资源"})
这里 @login_required
在执行视图函数前先检查是否有 Authorization
头,如果没有则返回 401
。
2. 上下文管理器(Context Manager)
特点
✅ 用于管理资源的生命周期(初始化 & 释放),比如数据库连接、文件操作。
✅ 通常与 with
语句一起使用,确保资源在使用后自动释放。
✅ 可以使用 @contextmanager
(简化)或 class
(完整实现)。
示例
python">from contextlib import contextmanager@contextmanager
def my_resource():print("资源初始化")yield "资源对象"print("资源清理")with my_resource() as res:print(f"正在使用: {res}")
输出:
资源初始化
正在使用: 资源对象
资源清理
应用场景
- 数据库会话管理
- 文件操作
- Flask 的应用上下文和请求上下文
- 事务处理(
commit
/rollback
)
Flask 中的数据库上下文管理
python">from contextlib import contextmanager
from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engineengine = create_engine("sqlite:///example.db")
Session = sessionmaker(bind=engine)@contextmanager
def get_db_session():"""管理数据库连接"""session = Session()try:yield session # 提供 sessionsession.commit() # 事务提交except Exception:session.rollback() # 事务回滚raisefinally:session.close() # 关闭连接@app.route('/data')
def get_data():with get_db_session() as session:result = session.execute("SELECT 'Hello Flask!'").fetchone()return result[0]
yield session
提供数据库连接。commit()
提交事务。rollback()
出错时回滚。close()
关闭连接,避免资源泄露。
3. Flask 装饰器 vs. 上下文管理器
特性 | 装饰器(Decorator) | 上下文管理器(Context Manager) |
---|---|---|
作用 | 修改/增强函数行为 | 管理资源的创建和释放 |
使用方式 | @ 语法修饰函数 | with 语句 |
常见用途 | Flask 路由、请求前后钩子、认证 | 数据库连接、文件操作、事务管理 |
是否修改原函数 | 是 | 否 |
何时执行 | 函数调用前后 | 进入/退出 with 代码块时 |
4. 结合使用装饰器 & 上下文管理器
装饰器和上下文管理器可以结合使用,例如,在 Flask 中使用装饰器封装数据库事务:
python">def transactional(f):"""装饰器封装事务"""@wraps(f)def wrapper(*args, **kwargs):with get_db_session() as session:return f(session, *args, **kwargs)return wrapper@app.route('/users')
@transactional
def get_users(session):"""获取用户列表"""return {"users": session.execute("SELECT * FROM users").fetchall()}
✅ transactional
作为装饰器
✅ get_db_session()
作为上下文管理器
✅ 自动管理数据库事务
5. 结论
- 装饰器:
- 修改函数的行为,增强功能(如 Flask 路由、认证)。
- 用
@
语法修饰函数,在函数调用时执行。 - 适用于权限验证、错误处理、日志等场景。
- 上下文管理器:
- 管理资源的生命周期(如数据库连接、文件操作)。
- 用
with
语句管理资源,确保正确释放。 - 适用于事务、应用上下文、请求上下文等。
- 两者可以结合,如用装饰器封装数据库事务,让代码更简洁优雅。
如果你的 Flask 项目中涉及资源管理(数据库、文件),建议结合使用两者,让代码更高效! 🚀