为何Django REST中管理员用户无法通过IsAdminUser权限验证?
Django REST框架管理员授权问题解决方案
问题根源
你遇到的未授权提示,核心原因是Django REST框架的IsAdminUser权限类,判断的是Django内置User模型的is_staff或is_superuser字段是否为True,但你创建Admin对象时,关联的User对象默认这两个属性都是False(create_user方法的默认值),所以权限验证直接失败。
具体修复步骤
1. 修复Admin创建逻辑,给关联User设置管理员属性
把AdminAPIViewSet中创建Admin的代码修改,直接给刚生成的django_user对象设置并保存管理员属性,不要用硬编码的pk=1001:
def create(self, request, *args, **kwargs): serializer = AdminSerializer(data=request.data) if serializer.is_valid(): email = serializer.data['email'] username = serializer.data['email'] password = serializer.data['password'] with transaction.atomic(): django_user = User.objects.create_user(username, email, password) # 给关联的User对象开启管理员权限 django_user.is_staff = True django_user.is_superuser = True django_user.save() admin = Admin.objects.create(**serializer.data, django_user=django_user) return Response(admin.pk) return Response({'error': 'Invalid data'}, status=status.HTTP_400_BAD_REQUEST)
注:
create_user方法创建的User默认is_staff和is_superuser都是False,必须显式设置并保存,才能让IsAdminUser权限类通过验证。
2. 优化AdminAPIViewSet的查询逻辑(可选但更合理)
当前的get_queryset让管理员只能查看自己的Admin数据,若需要管理员查看所有Admin数据,可调整为:
def get_queryset(self): user = self.request.user if user.is_authenticated: # 管理员返回所有Admin数据,普通用户仅返回自身关联数据 if user.is_staff or user.is_superuser: return Admin.objects.all() return Admin.objects.filter(username=user.admin.username) return Admin.objects.none() # 用ORM的none()比空列表更规范
3. 实现普通客户仅查看自身数据的权限逻辑
针对普通客户的只读视图(ClientReadOnlyAPIViewSet),需要自定义权限类,确保普通用户只能访问自己的客户数据,管理员可访问所有:
首先定义自定义权限类:
from rest_framework import permissions class IsOwnerOrAdmin(permissions.BasePermission): def has_object_permission(self, request, view, obj): # 管理员允许访问所有对象 if request.user.is_staff or request.user.is_superuser: return True # 普通用户仅能访问自己关联的Client对象 return obj.django_user == request.user
然后修改ClientReadOnlyAPIViewSet:
class ClientReadOnlyAPIViewSet(viewsets.ReadOnlyModelViewSet): queryset = Client.objects.all() serializer_class = ClientSerializer permission_classes = [permissions.IsAuthenticated, IsOwnerOrAdmin] def get_queryset(self): user = self.request.user if user.is_staff or user.is_superuser: return Client.objects.all() # 普通用户仅返回自身关联的Client数据 return Client.objects.filter(django_user=user)
4. 验证效果
- 创建Admin账号后,登录访问
/api/v1/clientslist/,应能查看所有客户数据 - 普通客户登录后访问
/api/v1/clients/,仅能看到自己的数据 - 未登录用户无法访问上述受权限保护的端点
内容的提问来源于stack exchange,提问作者RECUR
相关产品推荐
相关产品推荐

