如何在REST框架中获取OR权限而不是AND

Mad*_*bat 13 python django django-rest-framework

当REST框架检查权限时,似乎权限类是AND.也就是说,每个权限类都需要返回True才能被授予权限.这使得"如果你是超级用户,你可以访问任何东西,但如果你是普通用户,你需要显式权限"有点难以实现,你不能只返回False,它将失败整个堆栈.有没有办法可能有短路权限?像"如果授予此权限,请停止检查?" 或者其他一些处理这类案件的方法?

meh*_*sum 12

现在,DRF允许使用按位运算符来组合权限:&-and-和| -要么-。

从文档

如果它们继承自rest_framework.permissions.BasePermission,则可以使用标准的Python按位运算符来组合权限。例如,可以编写IsAuthenticatedOrReadOnly:

from rest_framework.permissions import BasePermission, IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView

class ReadOnly(BasePermission):
    def has_permission(self, request, view):
        return request.method in SAFE_METHODS

class ExampleView(APIView):
    permission_classes = (IsAuthenticated|ReadOnly,)

    def get(self, request, format=None):
        content = {
            'status': 'request was permitted'
        }
        return Response(content)
Run Code Online (Sandbox Code Playgroud)

编辑:请注意在后面有一个逗号IsAuthenticated|ReadOnly

  • 嗨mehamasum,你试试这个“|” 在代码中。是的,我发现文档说“|” 可以使用,但我收到错误“类型错误:| 不支持的操作数类型:‘类型’和‘类型’” (2认同)
  • @flytofuture 可能您正在使用旧版本的 DRF?您可以尝试升级软件包并重试吗? (2认同)
  • @flytofuture,`|` 和 `&` 出现在 [3.9](https://www.django-rest-framework.org/community/3.9-announcement/#composable-permission-classes),随后是 `~` [3.9.2](https://www.django-rest-framework.org/community/release-notes/#392) (2认同)
  • 请注意,`IsAuthenticated|ReadOnly` 后面有一个逗号。否则,会得到一个错误:`TypeError: 'OperandHolder' object is not iterable` (2认同)
  • 有可能以某种方式做这样的事情吗?权限类 = ((IsAuthenticated) | (ReadOnly & HasPermissionToken)) (2认同)

ian*_*kit 5

我想你可以在django-rules这里使用图书馆。关联

它是一个非常类似于决策树的基于规则的引擎,并且可以很容易地与 DRF 的 permissions_class 框架集成。

最好的部分是您可以对简单的权限执行设置操作并从中创建复杂的权限。

例子

>>> @rules.predicate
>>> def is_admin(user):
...     return user.is_staff 
...


>>> @rules.predicate
>>> def is_object_owner(user, object):
        return object.owner == user
Run Code Online (Sandbox Code Playgroud)

谓词几乎可以对给定的参数做任何事情,但如果它们检查的条件为真,则必须始终返回 True,否则返回 False。现在结合这两个谓词..

is_object_editable = is_object_owner | is_admin
Run Code Online (Sandbox Code Playgroud)

您可以is_object_editable在权限类的 has_permissions 方法中使用这个新的谓词规则。