如何编写Django中间件扩展request获取已认证用户的Group实例?
解决Django自定义中间件中匿名用户报错的问题
嘿,我来帮你搞定这个中间件的坑!你说已经加了request.user.is_authenticated判断还是报错,大概率是两个原因:要么你的判断逻辑没覆盖到所有匿名场景,要么当已认证用户还没关联Person实例时,直接访问request.user.auth_user会抛出异常。下面给你一个稳当的实现方式:
正确的GroupMiddleware实现
首先,我们要确保不管用户是否认证,request.mygroup都存在(哪怕是None),同时处理用户有账号但没创建Person实例的异常情况:
from django.contrib.auth.models import AnonymousUser from .models import Person, Group class GroupMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): # 先初始化mygroup为None,确保request始终有这个属性 request.mygroup = None # 双重校验用户是否已认证:先排除匿名用户实例,再校验认证状态 if not isinstance(request.user, AnonymousUser) and request.user.is_authenticated: try: # 获取当前用户绑定的Person实例 person = request.user.auth_user # 获取该用户所属的所有群组,你可以根据需求调整返回形式 user_groups = person.group_members.all() # 如果用户有群组,就赋值;否则保持None if user_groups.exists(): # 示例1:返回用户的第一个群组 request.mygroup = user_groups.first() # 示例2:返回用户所有群组的QuerySet # request.mygroup = user_groups except Person.DoesNotExist: # 若用户还没创建对应的Person记录,直接跳过,保持mygroup为None pass # 继续处理请求 response = self.get_response(request) return response
关键细节解释
- 初始化
request.mygroup:先把这个属性设为None,这样不管用户是匿名还是没有关联群组,都不会因为request.mygroup不存在而报错。 - 双重用户校验:有些场景下
request.user是AnonymousUser实例,但直接判断is_authenticated也会返回False,双重判断能更稳妥地过滤匿名用户。 - 异常捕获:已认证用户可能还没创建对应的
Person记录,直接访问request.user.auth_user会抛出Person.DoesNotExist异常,用try-except捕获后不会中断请求流程。 - 灵活返回群组:你可以根据业务需求选择返回单个群组(比如
first())或者所有群组的QuerySet,注释里给了两种示例。
注册中间件
最后别忘了在settings.py的MIDDLEWARE列表里注册这个中间件,一定要放在AuthenticationMiddleware之后,这样request.user才能被正确初始化:
MIDDLEWARE = [ # ... 其他默认中间件 'django.contrib.auth.middleware.AuthenticationMiddleware', # 添加你的自定义中间件,替换成你的app路径 'your_app_name.middleware.GroupMiddleware', # ... 其他中间件 ]
这样修改后,匿名用户访问时request.mygroup会是None,不会报错;已认证且有对应群组的用户能正常获取群组信息;已认证但没绑定Person的用户也不会触发异常。
内容的提问来源于stack exchange,提问作者user12188381
相关产品推荐
相关产品推荐

