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

相关推荐
FYKJ_20107 小时前
django药饮个性化推荐系统54839-计算机课程设计、毕业设计
vue.js·spring boot·python·mysql·typescript·spark·django
云浪8 小时前
通过 Goroutine 搞懂 Go 并发与常见的 9 个坑
后端·go
天赐范式8 小时前
天赐范式第175天:让活着的成员互相验证——异质互验与重放反伪造
python·数字生命·天赐范式·动态运行时·互验·重放反伪造
Wx-bishekaifayuan8 小时前
springboot贵州旅游系统55916-计算机课程设计、毕业设计
spring boot·后端·python·django·课程设计·express·旅游
计算机源码社8 小时前
【27届大数据毕设】基于Hadoop的跨境二手车价格对比可视化分析系统-基于K-Means与FPGrowth的二手车价格影响因素挖掘研究
大数据·hadoop·python·数据分析·spark·毕业设计·数据可视化
mldong8 小时前
事务不归引擎管:ITransactionTemplate,聚合一致性的最后一块拼图
后端·架构
IT_陈寒13 小时前
Java中equals方法比了个寂寞?原来这才是正确的重写姿势
前端·人工智能·后端
Thneonl13 小时前
Celery 生产踩坑:1000 任务积压与 acks_late 双重执行
后端·python
卷福同学13 小时前
第一次当面试官有感
后端·面试
苏三说技术13 小时前
为什么越来越多人用 OnlyOffice?
后端