You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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认证流程适配最好的方案:

  1. 自定义DRF权限类,把你的前置校验逻辑放到权限类中:
from rest_framework.permissions import BasePermission

class CheckPreconditionPermission(BasePermission):
    def has_permission(self, request, view):
        # DRF执行权限校验时已经完成了认证,request.user是认证后的用户
        return check_precondition(request.user)
  1. 在视图中引入该权限类,移除原有的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 09:45:02