Django中如何基于session实现查询预过滤 无需每次手动传入UUID参数
可以实现,你可以通过「自定义模型管理器 + 中间件存储请求上下文」的方案完成全局预过滤,无需在每次查询时手动传入UUID过滤条件,具体实现步骤如下:
实现步骤
1. 配置中间件存储当前请求的UUID
使用线程局部变量存储当前登录用户的UUID,避免不同请求之间的数据串扰。
首先在项目中新建middleware.py,添加如下代码:
import threading # 线程局部变量,每个请求对应独立的存储空间 local = threading.local() class UniqueNumMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): # 请求进入时存储session中的UUID local.unique_num = request.session.get('unique_num') response = self.get_response(request) # 请求结束后清除存储,防止线程复用时泄露数据 if hasattr(local, 'unique_num'): del local.unique_num return response
随后将该中间件添加到settings.py的MIDDLEWARE列表中,注意要放在django.contrib.sessions.middleware.SessionMiddleware之后,确保session已经初始化完成:
MIDDLEWARE = [ # ...其他默认中间件 'django.contrib.sessions.middleware.SessionMiddleware', # 新增你自定义的中间件 '你的应用名.middleware.UniqueNumMiddleware', # ...其他中间件 ]
2. 自定义带自动过滤的模型管理器
重写模型默认管理器的get_queryset方法,自动读取线程存储的UUID添加过滤条件:
from django.db import models from .middleware import local class AutoUniqueFilterManager(models.Manager): def get_queryset(self): base_queryset = super().get_queryset() # 存在登录用户UUID时自动加过滤,未登录场景可按业务需求调整逻辑 if hasattr(local, 'unique_num') and local.unique_num is not None: return base_queryset.filter(unique_num=local.unique_num) # 未登录场景默认返回全量,如需返回空可改为 return base_queryset.none() return base_queryset
3. 给业务模型绑定自定义管理器
将你需要自动过滤的模型的默认管理器替换为上面自定义的管理器即可:
class YourBusinessModel(models.Model): unique_num = models.UUIDField(verbose_name="关联UUID") # 其他业务字段... # 替换默认管理器,查询时自动加UUID过滤 objects = AutoUniqueFilterManager() # 保留原生管理器,特殊场景需要查全量数据时可以调用 raw_objects 查询 raw_objects = models.Manager()
使用效果
配置完成后,你在视图中直接执行data = YourBusinessModel.objects.filter()就会自动返回当前登录用户UUID关联的所有数据,无需再手动传入unique_num过滤条件。
注意事项
- 如果使用异步视图,线程局部变量不生效,需要改用Python 3.7+内置的
contextvars存储UUID,逻辑和上面一致。 - 涉及管理员后台、定时任务等非用户请求场景的查询,建议使用原生的
raw_objects管理器,避免自动过滤导致数据查询不全。
内容的提问来源于stack exchange,提问作者Vaibhav
相关产品推荐
相关产品推荐

