Become a sponsor

本章概要
Flask 的 g 对象是请求级别的全局变量容器,用于在同一请求的不同函数间共享数据。本文介绍 g 对象的使用方式、请求上下文机制,以及项目中 g 对象的实际应用场景。
g(global 的缩写)是 Flask 提供的请求级全局变量对象。它的生命周期与请求绑定:
请求进入 → 创建 g 对象
↓
路由处理 → 通过 g 存取数据
↓
响应返回 → 销毁 g 对象线程安全
每个请求有独立的 g 对象,不同请求之间的 g 互不影响。在多线程环境下,每个线程处理的请求都有自己的 g,不存在数据竞争。
from flask import g
# 在请求开始时设置
g.user_id = 1
g.username = 'admin'
# 在请求处理过程中获取
user_id = g.user_idAOP 事务拦截器通过 g 对象管理事务状态:
# 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)登录校验中间件将当前用户信息存入 g 对象,业务代码通过 get_user_id() 等函数获取:
# 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')# 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)业务代码通过这些函数获取当前用户信息:
# 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)事务拦截器通过 g 记录请求开始时间,用于计算响应耗时:
# 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 | 单个请求 | 是 | 请求级数据(当前用户、事务状态) |
session | 用户会话 | 是 | 用户级数据(登录状态、偏好设置) |
current_app.config | 应用生命周期 | 是 | 应用级配置(数据库 URI、密钥) |
| 模块级变量 | 进程生命周期 | 否 | 单例对象(扩展实例) |
注意事项
g 对象只能在请求上下文中访问,不能在请求外使用g 对象在请求结束后自动销毁,不要用于持久化数据Flask 的请求上下文机制确保 g、request、session 等对象在请求处理期间可用:
# 在请求上下文中可以访问 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 对象。