Skip to content

Flask g 对象与请求上下文 ​

本章概要

Flask 的 g 对象是请求级别的全局变量容器,用于在同一请求的不同函数间共享数据。本文介绍 g 对象的使用方式、请求上下文机制,以及项目中 g 对象的实际应用场景。

什么是 g 对象 ​

g(global 的缩写)是 Flask 提供的请求级全局变量对象。它的生命周期与请求绑定:

请求进入 → 创建 g 对象
    ↓
路由处理 → 通过 g 存取数据
    ↓
响应返回 → 销毁 g 对象

线程安全

每个请求有独立的 g 对象,不同请求之间的 g 互不影响。在多线程环境下,每个线程处理的请求都有自己的 g,不存在数据竞争。

基本用法 ​

python
from flask import g

# 在请求开始时设置
g.user_id = 1
g.username = 'admin'

# 在请求处理过程中获取
user_id = g.user_id

项目中的实际应用 ​

1. 事务状态管理 ​

AOP 事务拦截器通过 g 对象管理事务状态:

python
# src/middleware/transaction.py
from flask import g, request
from src.core.database import db


def register_transaction(app):
    """注册 AOP 事务拦截器"""

    @app.before_request
    def begin_transaction():
        """请求开始:记录开始时间,开启事务标记"""
        g.request_start_time = time.time()
        g.transaction_active = True

    @app.after_request
    def commit_transaction(response):
        """请求结束:自动提交事务"""
        if request.method in ("POST", "PUT", "DELETE", "PATCH"):
            if 200 <= response.status_code < 300:
                data = response.get_json(silent=True)
                if data and data.get("code", 0) == 0:
                    db.session.commit()
                else:
                    db.session.rollback()
        return response

    @app.teardown_request
    def cleanup_transaction(exception=None):
        """请求结束:清理资源"""
        if exception:
            db.session.rollback()
        g.pop("transaction_active", None)
        g.pop("request_start_time", None)

2. 当前用户信息 ​

登录校验中间件将当前用户信息存入 g 对象,业务代码通过 get_user_id() 等函数获取:

python
# src/middleware/auth.py
from flask import g, request
from src.core.jwt import decode_token


def register_middleware(app):
    """注册登录校验中间件(实际位于 src/middleware/auth.py)"""

    @app.before_request
    def login_required():
        """登录校验:解析 JWT Token,注入用户信息到 g 对象"""
        # 白名单路径跳过校验
        if _is_whitelist_path(request.path):
            return

        # 提取 Token
        token = request.headers.get('Authorization', '').replace('Bearer ', '')
        if not token:
            return R.failed(msg="未登录", code=401)

        # 解析 Token
        payload = decode_token(token)
        if not payload:
            return R.failed(msg="Token 无效", code=401)

        # 注入用户信息到 g 对象
        g.user_id = payload.get('user_id')
        g.username = payload.get('username')
        g.realname = payload.get('realname')
python
# src/core/security.py
from flask import g


def get_user_id():
    """获取当前登录用户ID"""
    return getattr(g, 'user_id', None)


def get_username():
    """获取当前登录用户名"""
    return getattr(g, 'username', None)


def get_realname():
    """获取当前登录用户真实姓名"""
    return getattr(g, 'realname', None)

业务代码通过这些函数获取当前用户信息:

python
# src/modules/system/position/service.py
from src.core.security import get_realname

class PositionService(BaseService):
    @classmethod
    def add(cls, data: dict) -> None:
        """新增岗位"""
        form = cls._validate_form(data)
        create_data = cls._clean_form_data(form)
        create_data["create_user"] = get_realname()  # 从 g 对象获取
        create_data["update_user"] = get_realname()
        cls.repository.create(**create_data)

3. 性能监控 ​

事务拦截器通过 g 记录请求开始时间,用于计算响应耗时:

python
# src/middleware/transaction.py
@app.after_request
def commit_transaction(response):
    elapsed = time.time() - g.get("request_start_time", time.time())
    logger.debug(
        f"请求结束, method: {request.method}, path: {request.path}, "
        f"status: {response.status_code}, elapsed: {elapsed:.3f}s"
    )
    return response

g 对象 vs 其他存储方式 ​

存储方式生命周期线程安全适用场景
g单个请求是请求级数据(当前用户、事务状态)
session用户会话是用户级数据(登录状态、偏好设置)
current_app.config应用生命周期是应用级配置(数据库 URI、密钥)
模块级变量进程生命周期否单例对象(扩展实例)

注意事项

  • g 对象只能在请求上下文中访问,不能在请求外使用
  • g 对象在请求结束后自动销毁,不要用于持久化数据
  • 需要跨请求共享的数据应使用 Redis 或数据库

请求上下文 ​

Flask 的请求上下文机制确保 g、request、session 等对象在请求处理期间可用:

python
# 在请求上下文中可以访问 g
with app.test_request_context():
    g.user_id = 1
    print(g.user_id)  # 正常访问

# 在请求上下文外访问 g 会报错
# print(g.user_id)  # RuntimeError: Working outside of application context.

总结 ​

g 对象是 Flask 请求级全局变量容器,项目中用于存储当前用户信息(user_id / username / realname)、事务状态(transaction_active)、请求开始时间(request_start_time)等请求级数据。通过 get_user_id() / get_realname() 等安全函数封装访问,业务代码无需直接操作 g 对象。

小蚂蚁云团队 · 提供技术支持