Django中UserPassesTestMixin的test_func获取到AnonymousUser问题
问题原因
这个问题的核心是Django原生的UserPassesTestMixin执行时机早于Django REST Framework(DRF)的认证流程:
- Django自带的
AuthenticationMiddleware只会处理基于Session的登录态,将request.user赋值为会话对应的用户。如果你使用的是DRF的Token认证、JWT认证等非Session认证方案,Django中间件层面不会识别这类认证凭证,此时request.user默认是AnonymousUser。 UserPassesTestMixin的test_func是在Django的视图分发(dispatch)逻辑中执行的,执行时机早于DRF自身dispatch方法中的认证步骤。等到DRF完成认证、进入视图的get/post等方法时,request.user才会被替换为认证通过的用户。
解决方案
优先推荐使用DRF原生的权限体系实现校验,这是和DRF认证流程适配最好的方案:
- 自定义DRF权限类,把你的前置校验逻辑放到权限类中:
from rest_framework.permissions import BasePermission class CheckPreconditionPermission(BasePermission): def has_permission(self, request, view): # DRF执行权限校验时已经完成了认证,request.user是认证后的用户 return check_precondition(request.user)
- 在视图中引入该权限类,移除原有的
UserPassesTestMixin即可:
class SomeTestView(APIView): permission_classes = [CheckPreconditionPermission] def get(self, request): print("inside view") print("user: ", request.user) print("is_authenticated? ", request.user.is_authenticated) return Response({"status": "success"})
如果你确实需要保留UserPassesTestMixin的使用,可以重写视图的dispatch方法,调整执行顺序,先触发DRF的认证逻辑再执行前置校验:
class SomeTestView(UserPassesTestMixin, APIView): def dispatch(self, request, *args, **kwargs): # 先执行DRF的初始化逻辑,包含认证、节流等步骤 self.initial(request, *args, **kwargs) # 再执行UserPassesTestMixin的前置校验 if not self.test_func(): return self.handle_no_permission() # 跳过父类的重复初始化,直接执行视图方法 return super(APIView, self).dispatch(request, *args, **kwargs) def test_func(self): return check_precondition(self.request.user) def get(self, request): # 原有逻辑
内容的提问来源于stack exchange,提问作者Aldo
相关产品推荐
相关产品推荐

