Python 之 Flask 的全局变量 g

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 中。

相关推荐
写码跑山的老艾25 分钟前
优惠券为何能反复使用?一次算价与提单不一致的资损复盘
后端
RAG学徒loading1 小时前
我把 RAG 召回从 57.6% 做到 78.8%,然后发现 75% 的真实问题它答不了
后端
用户42569399996201 小时前
我的 HashMap 查找全废了,但 36 个测试全绿
后端
小番茄程序猿1 小时前
Redis 编码压测 59 轮:HSET 快 23 倍是假象,SMEMBERS 慢 30 倍是真的
redis·后端
曲径海盗1 小时前
【Python 学习第 53 天】列表基础
python·学习笔记·编程入门
Moment1 小时前
代码都能让 Agent 写了,我们为什么还要学前端?
前端·后端·面试
Dumbness1 小时前
群里 @ 机器人发"查订单",指令一条都没命中:微信群机器人在路由前漏掉的几步归一化
python·微信
AI入职记2 小时前
Spring AI 实测:不挂工具,模型真的会瞎编吗?
后端·ai编程
wei_shuo2 小时前
SQL Server数据迁移实战:内置故障诊断工具与根因分析实践
后端