Как установить разрешения для каждой функции обработчика с APIView? - PullRequest
1 голос
/ 29 марта 2020

Я пишу API для небольшого школьного проекта, используя Django и Django -Rest-Framework. Я пытаюсь выяснить права доступа.

Я использую APIView для своих представлений и пытаюсь установить разные разрешения для каждого метода-обработчика без написания дополнительных представлений.

Вот одно из представлений для модуля блога, который у меня есть:

(Это представление используется для /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, хотя изменение этого значения не обязательно поможет, поскольку я все равно придется менять некоторые разрешения индивидуально.

Так что я должен быть в состоянии сделать GET-запрос, пока он не аутентифицирован, до /posts/ и получить список всех сообщений, в то время как я должен получить 401 от запроса POST до /posts/. Однако даже запрос GET возвращает код состояния 401.

Как правильно сделать это ... если есть хотя бы один.

Редактировать: Хотя Я дал ответ на свой вопрос, но мне все равно хотелось бы узнать, есть ли еще правильные способы решения этой проблемы.

1 Ответ

0 голосов
/ 29 марта 2020

Я нашел решение, хотя я не уверен, что это лучший способ сделать это.

Сначала мы создаем подкласс 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 для записи представлений и используйте dict для permission_classes, где ключами являются методы.

Пример:

# 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)
...