简体   繁体   English

如何在 Django Rest 框架中将 has_object_permission 与 APIView 一起使用?

[英]How to use has_object_permission with APIView in Django Rest Framework?

Hi everyone I want to use a custom permission with APIView in my class UserDetail but I noticed that this permission is not executing, my permission is called "IsOwner", because I want to allow users to modify his own information based on the user id.大家好,我想在我的 class UserDetail 中使用 APIView 的自定义权限,但我注意到这个权限没有执行,我的权限称为“IsOwner”,因为我想允许用户根据用户 ID 修改自己的信息。 Every time that I make a request I got an error:每次我提出请求时,我都会收到一个错误:

{
    "detail": "Not found."
}

views.py视图.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权限.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) this line is not working) 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)

If you need the operator Or,you can import rest_condition:如果你需要运算符或者,你可以导入rest_condition:

pip install rest_condition

And in your view import Or from rest_condition and do the following on the permission_classes:在您看来 import Or from rest_condition 并在 permission_classes 上执行以下操作:

permission_classes = [Or(CustomObjectPermissions,IsOwner)]

But I don't think the error is caused because Or is missing,you can tackle this problem from another prespective, you can have the get request returning only that user's information so he can modify:但我不认为错误是因为 Or 丢失引起的,你可以从另一个角度解决这个问题,你可以让 get 请求只返回该用户的信息,以便他可以修改:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM