Как использовать has_object_permission с APIView в Django Rest Framework? - PullRequest
1 голос
/ 17 июня 2020

Всем привет! Я хочу использовать настраиваемое разрешение с APIView в моем классе UserDetail, но я заметил, что это разрешение не выполняется, мое разрешение называется «IsOwner», потому что я хочу разрешить пользователям изменять свою собственную информацию на основе Логин пользователя. Каждый раз, когда я делаю запрос, я получаю сообщение об ошибке:

{
    "detail": "Not found."
}

views.py

from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework import status, permissions, generics, viewsets
from rest_framework.response import Response
from rest_framework.views import APIView

from .serializers import MyTokenObtainPairSerializer, UserSerializer, GroupSerializer
from .models import User
from authentication.permisssions import CustomObjectPermissions, IsOwner
from django.contrib.auth.models import Group
from django.http import Http404

class ObtainTokenPairView(TokenObtainPairView):
    permission_classes = [permissions.AllowAny,]
    serializer_class = MyTokenObtainPairSerializer

class UserList(APIView):
    """
    List all snippets, or create a new snippet.
    """
    permission_classes = [CustomObjectPermissions]
    serializer_class = UserSerializer

    def get_queryset(self):
        users = User.objects.all().order_by('-date_joined')
        return users

    def get(self, request, format=None):

        serializer_context = {
        'request': request,
        }
        serializer = UserSerializer(self.get_queryset(), context=serializer_context, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer_context = {
        'request': request,
        }
        serializer = UserSerializer(data=request.data, context=serializer_context)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class UserDetail(APIView):
    """
    Retrieve, update or delete a snippet instance.
    """

    permission_classes = [CustomObjectPermissions|IsOwner]

    serializer_class = UserSerializer

    def get_queryset(self):
        pk = self.kwargs["pk"]
        return User.objects.filter(id = pk)

    def get_object(self, pk):
        try:
            print(pk)
            user = User.objects.get(pk=pk)
            self.check_object_permissions(self.request, user)

            return user
        except User.DoesNotExist:

            raise Http404

    def get(self, request, pk, format=None):

        user = self.get_object(pk)
        serializer_context = {
        'request': request,
        }
        serializer = UserSerializer(user, context=serializer_context)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        user = self.get_object(pk)
        serializer_context = {
        'request': request,
        }
        serializer = UserSerializer(user,context=serializer_context, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        user = self.get_object(pk)
        user.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

class GroupList(APIView):
    """
    List all snippets, or create a new snippet.
    """
    permission_classes = [CustomObjectPermissions]
    queryset = Group.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer

    def get(self, request, format=None):
        groups = Group.objects.all()
        serializer_context = {
        'request': request,
        }
        serializer = GroupSerializer(groups, context=serializer_context, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer_context = {
        'request': request,
        }
        serializer = GroupSerializer(data=request.data, context=serializer_context)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class GroupDetail(APIView):
    """
    Retrieve, update or delete a snippet instance.
    """

    permission_classes = [CustomObjectPermissions]
    queryset = Group.objects.all().order_by('-date_joined')
    serializer_class = GroupSerializer


    def get_object(self, pk):
        try:
            return Group.objects.get(pk=pk)
        except Group.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        group = self.get_object(pk)
        serializer_context = {
        'request': request,
        }
        serializer = GroupSerializer(group, context=serializer_context)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        group = self.get_object(pk)
        serializer_context = {
        'request': request,
        }
        serializer = GroupSerializer(group,context=serializer_context, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        group = self.get_object(pk)
        group.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

permissions.py

from rest_framework.permissions import DjangoObjectPermissions, BasePermission

class CustomObjectPermissions(DjangoObjectPermissions):
    """
    Similar to `DjangoObjectPermissions`, but adding 'view' permissions.
    """
    perms_map = {
        'GET': ['%(app_label)s.view_%(model_name)s'],
        'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
        'HEAD': ['%(app_label)s.view_%(model_name)s'],
        'POST': ['%(app_label)s.add_%(model_name)s'],
        'PUT': ['%(app_label)s.change_%(model_name)s'],
        'PATCH': ['%(app_label)s.change_%(model_name)s'],
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
    }

class IsOwner(BasePermission):
    message = 'You must be the owner of this object'

    def has_object_permission(self, request, view, obj):
        return obj.id == request.user.id

views.py (self .check_object_permissions (self.request, user) эта строка не работает)

from rest_framework_simplejwt.views import TokenObtainPairView
from rest_framework import status, permissions, generics, viewsets
from rest_framework.response import Response
from rest_framework.views import APIView

from .serializers import MyTokenObtainPairSerializer, UserSerializer, GroupSerializer
from .models import User
from authentication.permisssions import CustomObjectPermissions, IsOwner
from django.contrib.auth.models import Group
from django.http import Http404

class ObtainTokenPairView(TokenObtainPairView):
    permission_classes = [permissions.AllowAny,]
    serializer_class = MyTokenObtainPairSerializer

class UserList(APIView):
    """
    List all snippets, or create a new snippet.
    """
    permission_classes = [CustomObjectPermissions]
    serializer_class = UserSerializer

    def get_queryset(self):
        users = User.objects.all().order_by('-date_joined')
        return users

    def get(self, request, format=None):

        serializer_context = {
        'request': request,
        }
        serializer = UserSerializer(self.get_queryset(), context=serializer_context, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer_context = {
        'request': request,
        }
        serializer = UserSerializer(data=request.data, context=serializer_context)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

class UserDetail(APIView):
    """
    Retrieve, update or delete a snippet instance.
    """

    permission_classes = [CustomObjectPermissions|IsOwner]

    serializer_class = UserSerializer

    def get_queryset(self):
        pk = self.kwargs["pk"]
        return User.objects.filter(id = pk)

    def get_object(self, pk):
        try:
            print(pk)
            user = User.objects.get(pk=pk)
            self.check_object_permissions(self.request, user)

            return user
        except User.DoesNotExist:

            raise Http404

    def get(self, request, pk, format=None):

        user = self.get_object(pk)
        serializer_context = {
        'request': request,
        }
        serializer = UserSerializer(user, context=serializer_context)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        user = self.get_object(pk)
        serializer_context = {
        'request': request,
        }
        serializer = UserSerializer(user,context=serializer_context, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        user = self.get_object(pk)
        user.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

class GroupList(APIView):
    """
    List all snippets, or create a new snippet.
    """
    permission_classes = [CustomObjectPermissions]
    queryset = Group.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer

    def get(self, request, format=None):
        groups = Group.objects.all()
        serializer_context = {
        'request': request,
        }
        serializer = GroupSerializer(groups, context=serializer_context, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        serializer_context = {
        'request': request,
        }
        serializer = GroupSerializer(data=request.data, context=serializer_context)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)


class GroupDetail(APIView):
    """
    Retrieve, update or delete a snippet instance.
    """

    permission_classes = [CustomObjectPermissions]
    queryset = Group.objects.all().order_by('-date_joined')
    serializer_class = GroupSerializer


    def get_object(self, pk):
        try:
            return Group.objects.get(pk=pk)
        except Group.DoesNotExist:
            raise Http404

    def get(self, request, pk, format=None):
        group = self.get_object(pk)
        serializer_context = {
        'request': request,
        }
        serializer = GroupSerializer(group, context=serializer_context)
        return Response(serializer.data)

    def put(self, request, pk, format=None):
        group = self.get_object(pk)
        serializer_context = {
        'request': request,
        }
        serializer = GroupSerializer(group,context=serializer_context, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        group = self.get_object(pk)
        group.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

1 Ответ

0 голосов
/ 18 июня 2020

Если вам нужен оператор Or, вы можете импортировать rest_condition:

pip install rest_condition

И в вашем представлении import Or from rest_condition и выполните следующие действия с классами разрешений:

permission_classes = [Or(CustomObjectPermissions,IsOwner)]

Но Я не думаю, что ошибка вызвана тем, что Или отсутствует, вы можете решить эту проблему с другой стороны, вы можете получить запрос на получение, возвращающий только информацию этого пользователя, чтобы он мог изменить:

def get_queryset(self):
   serializer = self.get_serializer()
   owner = serializer.context['request'].user
   return User.objects.filter(id=owner.id)
...