python 如何使用APIView设置每个处理函数的权限?

sirbozc5  于 2023-03-06  发布在  Python
关注(0)|答案(2)|浏览(141)

我正在使用Django和Django-Rest-Framework为一个小型的学校相关项目编写API。我正在尝试弄清楚权限。
我正在使用APIView作为我的视图,并且希望在不编写更多视图的情况下为每个处理程序方法设置不同的权限。
下面是我所拥有的blog模块的一个视图:
(This视图用于/posts/

from .serializers import *
from django.db.models import Case, When
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.decorators import permission_classes
from rest_framework import status, permissions

# Create your views here.
class PostList(APIView):
    """
    API Endpoint to List Posts
    METHODS: GET, POST
    """

    @permission_classes([permissions.AllowAny,])
    def get(self, request, format=None):
        posts = Post.objects.all()
        serializer = PostSerializer(posts, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    @permission_classes([permissions.IsAuthenticated])
    def post(self, request, format=None):
        serializer = PostCreationSerializer(data=request.data)
        if serializer.is_valid():
            obj = serializer.save()
            data = serializer.data
            data["id"] = obj.id
            return Response(data, status=status.HTTP_201_CREATED)
        return Response(status=status.HTTP_400_BAD_REQUEST)

当前的默认值是permissions.IsAuthenticated,尽管更改它不一定有帮助,因为我仍然需要单独更改一些权限。
因此,我应该能够在没有对/posts/进行身份验证的情况下发出GET请求,并获得所有帖子的列表,同时我应该从对/posts/的POST请求中获得401。
什么是正确的方法来做这件事...如果有一个。

**编辑:**虽然我提供了自己问题的答案,但我仍然想知道是否有更正确的方法来解决这个问题。

xmd2e60i

xmd2e60i1#

我想出了一个解决办法,虽然我不确定这是不是最好的办法。
首先,我们创建一个APIView的子类:

from rest_framework.views import APIView

class CustomAPIView(APIView):
    def get_permissions(self):
        # Instances and returns the dict of permissions that the view requires.
        return {key: [permission() for permission in permissions] for key, permissions in self.permission_classes.items()}

    def check_permissions(self, request):
        # Gets the request method and the permissions dict, and checks the permissions defined in the key matching
        # the method.
        method = request.method.lower()
        for permission in self.get_permissions()[method]:
            if not permission.has_permission(request, self):
                self.permission_denied(
                    request, message=getattr(permission, 'message', None)
                )

然后,我们使用这个CustomAPIView写出视图,并对permission_classes使用一个dict,其中键是方法。
示例:

# Create your views here.
class PostList(CustomAPIView):
    """
    API Endpoint to List Posts
    METHODS: GET, POST
    """
    permission_classes = {"get": [permissions.AllowAny], "post": [permissions.IsAuthenticated]}

    def get(self, request, format=None):
        posts = Post.objects.all()
        serializer = PostSerializer(posts, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def post(self, request, format=None):
        serializer = PostCreationSerializer(data=request.data)
        if serializer.is_valid():
            obj = serializer.save()
            data = serializer.data
            data["id"] = obj.id
            return Response(data, status=status.HTTP_201_CREATED)
        return Response(status=status.HTTP_400_BAD_REQUEST)
huus2vyu

huus2vyu2#

虽然我已提出一个解决办法,但我不确定这是否最佳办法。
因此,您可以覆盖APIView类的get_permissions()。然后将您的权限添加到特定方法。
这是一个将IsAuthenticated权限添加到post方法的示例。

def get_permissions(self):
    permissions = super().get_permissions()

    if self.request.method.lower() == 'post':
        permissions.append(IsAuthenticated())

    return permissions

"我希望这能帮上忙"

相关问题