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

为何DjangoObjectPermissions对管理员用户不生效?

问题描述

我配置了DjangoObjectPermissions,该权限对普通用户完全生效,但对管理员用户无效。


models.py

class Transformer(models.Model):
    name = models.CharField(max_length=150, unique=True)
    alternate_mode = models.CharField(
        max_length=250,
        blank=True,
        null=True)
    description = models.CharField(
        max_length=500,
        blank=True,
        null=True)
    alive = models.BooleanField(default=False)

    class Meta:
        ordering = ('name',)

    def __str__(self):
        return self.name

serializers.py

class TransformerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Transformer
        fields = "__all__"

views.py

class TransformerList(generics.ListCreateAPIView):
    queryset = Transformer.objects.all()
    serializer_class = TransformerSerializer
    permission_classes = [DjangoObjectPermissions, ]

    def perform_create(self, serializer):
        instance = serializer.save()
        assign_perm("delete_transformer", self.request.user, instance)

class TransformerDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Transformer.objects.all()
    serializer_class = TransformerSerializer
    permission_classes = [DjangoObjectPermissions, ]

settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'snippets',
    'class_based_api_views',
    'guardian'
]

AUTHENTICATION_BACKENDS = (
    'django.contrib.auth.backends.ModelBackend',
    'guardian.backends.ObjectPermissionBackend',
)

测试情况

  • 创建管理员用户(用户名:admin)
  • 创建普通用户(用户名:user3)

用user3创建一条Transformer记录后:

  • 对象权限显示仅user3拥有该记录的删除权限
  • user3可删除自己创建的记录,符合预期
  • 管理员无需配置任何对象权限,即可对该记录执行编辑/删除操作,不符合预期

问题

为何管理员用户在没有对应权限的情况下仍能编辑/删除对象?


解答

这是因为Django的超级用户(管理员)默认拥有is_superuser属性,而DRF的DjangoObjectPermissions权限类会直接放行超级用户的所有操作。

DjangoObjectPermissions继承自DjangoModelPermissions,后者的源码逻辑中明确:只要用户是超级用户(request.user.is_superuser为True),权限验证会直接返回通过,不会再检查具体的对象权限。

要解决这个问题,你需要自定义一个权限类,移除超级用户的默认放行逻辑,强制校验对象权限:

# 可放在views.py或单独的permissions.py文件中
from rest_framework.permissions import DjangoObjectPermissions

class StrictDjangoObjectPermissions(DjangoObjectPermissions):
    def has_permission(self, request, view):
        # 跳过超级用户直接通过的逻辑,仅执行基础权限检查
        return super(DjangoObjectPermissions, self).has_permission(request, view)
    
    def has_object_permission(self, request, view, obj):
        # 强制执行对象权限校验,不判断用户是否为超级用户
        return super().has_object_permission(request, view, obj)

之后在视图中替换原有的权限类:

class TransformerList(generics.ListCreateAPIView):
    # 保留其他配置
    permission_classes = [StrictDjangoObjectPermissions, ]

class TransformerDetail(generics.RetrieveUpdateDestroyAPIView):
    # 保留其他配置
    permission_classes = [StrictDjangoObjectPermissions, ]

这种方式直接可控,也可以通过修改guardian的全局配置限制超级用户,但自定义权限类的方案更灵活。


内容的提问来源于stack exchange,提问作者Parth

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 15:45:34