Django REST Framework-每个方法的单独权限

2024-06-06 19:57:34 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用Django REST框架编写一个API,我想知道在使用基于类的视图时是否可以为每个方法指定权限。

Reading the documentation我认为,如果您正在编写基于函数的视图,只需在要用权限保护的视图的函数上使用@permission_classes装饰器,就很容易做到这一点。但是,在使用带有APIView类的CBVs时,我看不到这样做的方法,因为然后我使用permission_classes属性指定完整类的权限,但这将应用于所有类方法(getpostput…)。

那么,是否可以用cbv编写API视图,并为视图类的每个方法指定不同的权限?


Tags: thedjango方法函数框架视图restapi
3条回答

我遇到了这个问题,真的想使用@permission_classes装饰器标记一些具有特定权限的自定义视图方法。最后我想到了一个混音:

class PermissionsPerMethodMixin(object):
    def get_permissions(self):
        """
        Allows overriding default permissions with @permission_classes
        """
        view = getattr(self, self.action)
        if hasattr(view, 'permission_classes'):
            return [permission_class() for permission_class in view.permission_classes]
        return super().get_permissions()

示例用例:

from rest_framework.decorators import action, permission_classes  # other imports elided

class MyViewset(PermissionsPerMethodMixin, viewsets.ModelViewSet):
    permission_classes = (IsAuthenticatedOrReadOnly,)  # used for default ViewSet endpoints
    queryset = MyModel.objects.all()
    serializer_class = MySerializer

    @action(detail=False, methods=['get'])
    @permission_classes((IsAuthenticated,))  # overrides IsAuthenticatedOrReadOnly
    def search(self, request):
        return do_search(request)  # ...

权限应用于整个视图类,但您可以在授权决策中考虑请求的各个方面(如GET或POST方法)。

请参见内置的IsAuthenticatedOrReadOnly作为示例:

SAFE_METHODS = ['GET', 'HEAD', 'OPTIONS']

class IsAuthenticatedOrReadOnly(BasePermission):
    """
    The request is authenticated as a user, or is a read-only request.
    """

    def has_permission(self, request, view):
        if (request.method in SAFE_METHODS or
            request.user and
            request.user.is_authenticated()):
            return True
        return False

我在使用CBV时遇到了同样的问题,因为根据请求方法,我有相当复杂的权限逻辑。

我想出的解决方案是使用本页底部列出的第三方“rest_condition”应用程序

http://www.django-rest-framework.org/api-guide/permissions

https://github.com/caxap/rest_condition

我只是分割了权限流逻辑,以便根据请求方法运行每个分支。

from rest_condition import And, Or, Not

class MyClassBasedView(APIView):

    permission_classes = [Or(And(IsReadOnlyRequest, IsAllowedRetrieveThis, IsAllowedRetrieveThat),
                             And(IsPostRequest, IsAllowedToCreateThis, ...),
                             And(IsPutPatchRequest, ...),
                             And(IsDeleteRequest, ...)]

因此“或”决定了根据请求方法运行权限的哪个分支,“和”包装了与接受的请求方法相关的权限,因此必须全部通过才能授予权限。您还可以在每个流中混合“或”、“和”和“不”以创建更复杂的权限。

运行每个分支的权限类如下所示

class IsReadyOnlyRequest(permissions.BasePermission):

    def has_permission(self, request, view):
        return request.method in permissions.SAFE_METHODS


class IsPostRequest(permissions.BasePermission):

    def has_permission(self, request, view):
        return request.method == "POST"


... #You get the idea

相关问题 更多 >