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

DRF重写get_permissions遇TypeError:权限类无法用|运算

问题解决:Django DRF权限类组合报错TypeError

错误原因

你直接用|运算符组合自定义权限类实例(比如IsSuperAdmin()|IsOwner())是不被支持的,因为Django REST Framework的BasePermission基类没有实现__or__运算符,无法通过这种方式实现"或"逻辑的权限判断。另外你的代码还存在缩进错误(GET分支和else分支的return语句缩进不正确),这也会导致代码运行异常。

解决方案

下面提供两种可行的解决方法,你可以根据需求选择:

方法一:自定义OR组合权限类

编写一个通用的OrPermission类,用来包装多个权限类,只要其中任意一个权限通过,就允许访问:

在permissions.py中添加:

class OrPermission(BasePermission):
    def __init__(self, *permissions):
        self.permissions = permissions

    def has_permission(self, request, view):
        # 只要有一个权限类的has_permission返回True,就通过
        return any(perm.has_permission(request, view) for perm in self.permissions)

    def has_object_permission(self, request, view, obj):
        # 处理对象级权限,同样只要有一个权限类通过就允许
        return any(perm.has_object_permission(request, view, obj) for perm in self.permissions)

然后修改views.py中的get_permissions方法,修复缩进并使用OrPermission组合权限:

class UserView(RetrieveUpdateDestroyAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    http_method_names = ['patch', 'get', 'delete']

    def get_permissions(self):
        if self.request.method == 'GET':
            return [IsAuthenticated(), OrPermission(IsSuperAdmin(), IsOwner(), IsAdmin())]
        elif self.request.method == 'DELETE':
            return [IsAuthenticated(), OrPermission(IsSuperAdmin(), IsAdmin())]
        else:
            return [IsAuthenticated(), OrPermission(IsSuperAdmin(), IsAdmin(), IsOwner())]

方法二:合并权限逻辑到单个类

把需要"或"逻辑的权限判断直接合并到一个自定义权限类中,减少代码复杂度:

在permissions.py中添加两个组合权限类:

class IsSuperAdminOrAdmin(BasePermission):
    message = "You must be super admin or admin to perform requested operation"

    def has_permission(self, request, view):
        return request.user.role in ["super_admin", "admin"]


class IsSuperAdminOrAdminOrOwner(BasePermission):
    message = "You must be super admin, admin, or owner of the resource to perform requested operation"

    def has_permission(self, request, view):
        return request.user.role in ["super_admin", "admin"]

    def has_object_permission(self, request, view, obj):
        # 要么是超级管理员/管理员,要么是资源所有者
        return self.has_permission(request, view) or obj.id == request.user.id

然后修改views.py:

class UserView(RetrieveUpdateDestroyAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    http_method_names = ['patch', 'get', 'delete']

    def get_permissions(self):
        if self.request.method == 'GET':
            return [IsAuthenticated(), IsSuperAdminOrAdminOrOwner()]
        elif self.request.method == 'DELETE':
            return [IsAuthenticated(), IsSuperAdminOrAdmin()]
        else:
            return [IsAuthenticated(), IsSuperAdminOrAdminOrOwner()]

额外注意点

  • 检查IsOwner类的拼写错误:operaton应该修正为operation。
  • 若使用DRF最新版本,虽然官方开始支持用|和&组合权限,但自定义权限类需确保运算符逻辑被正确实现,上述两种方法兼容性更强。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 01:30:20