Flask 的 g 对象是一个专为单次请求 设计的临时全局存储工具-。用来在同一个请求的不同函数(如钩子函数和视图函数)之间方便地共享数据,从而避免通过函数参数层层传递。
我印象最深的当属 Knowflow 项目中的 knowflow-backend 后端服务。KnowFlow 为了不修改 ragflow 的核心代码,采用插件化微服务架构,作为独立服务增强 RAGFlow。因此,大部分与 ragflow 的交互是通过 api 接口调用实现的。
变量设置
既然涉及到 api 调用,那就涉及到用户身份和权限校验的问题。因此,在 before_request 的统一入口钩子函数中,我们可以调用 get_current_user() 函数,通过请求 Header 中 Authorization 包含的相关 api_token 中,解析获取用户相关的信息并赋值到全局变量 g 中。
python
from flask import Flask, jsonify, request, g
app = Flask(__name__)
# 启用CORS,允许前端访问
CORS(app, resources={r"/api/*": {"origins": "*"}}, supports_credentials=True)
# ...
# 在Flask的g对象中存储用户信息
@app.before_request
def load_user_info():
"""在每个请求前加载用户信息"""
# 跳过不需要用户信息的路径
excluded_paths = ['/health', '/api/v1/auth/login', '/']
if request.path in excluded_paths or not request.path.startswith('/api/'):
return
user_info = get_current_user()
if user_info:
g.current_user_id, g.current_user_role, g.current_user_name, g.current_user_email = user_info
g.manageable_user_ids = get_manageable_user_ids(g.current_user_id, g.current_user_role)
else:
g.current_user_id = None
g.current_user_role = None
g.current_user_name = None
g.current_user_email = None
g.manageable_user_ids = None
变量获取
然后,在后续的其他视图函数中,我们可以使用类似于下面
current_user_id = getattr(g, 'current_user_id', None)
的方式直接从 g 中获取钩子函数中设置好的变量然后继续后续的使用。
python
@teams_bp.route('', methods=['GET'])
def get_teams():
"""获取团队列表的API端点,支持分页和条件查询"""
try:
# 获取查询参数
current_page = int(request.args.get('current_page', request.args.get('currentPage', 1)))
page_size = int(request.args.get('size', 10))
team_name = request.args.get('name', '')
# 调用服务函数获取分页和筛选后的团队数据
current_user_id = getattr(g, 'current_user_id', None)
user_role = getattr(g, 'current_user_role', None)
teams, total = get_teams_with_pagination(current_page, page_size, team_name, current_user_id, user_role)
# 返回符合前端期望格式的数据
return jsonify({
"code": 0,
"data": {
"list": teams,
"total": total
},
"message": "获取团队列表成功"
})
except Exception as e:
# 错误处理
return jsonify({
"code": 500,
"message": f"获取团队列表失败: {str(e)}"
}), 500
变量周期
-
请求隔离 :
g对象在一次请求中全局可用,但每个请求都有自己独立的g对象,互不干扰。 -
线程安全 :
g是线程隔离的,能保证在多线程环境下数据安全。 -
自动清理 :请求结束时,
g对象及其存储的数据会被自动销毁,确保每次请求都从全新的g开始。生命周期仅限于单次请求。
使用场景
典型的使用场景则是在钩子函数与视图函数间传递数据 :在 before_request 中完成用户鉴权、数据库连接等预处理,将结果存入 g,供后续视图函数直接使用。例如,在 before_request 中查询当前用户信息并存入 g.user 中。