ViewSet 的 Django 休息框架自定义权限

Django rest framework custom permission for ViewSet

这是我的模型视图集

class UserViewSet(viewsets.ModelViewSet):
    def list(self, request):
        users = User.objects.all()
        serializer = UserSerializer(users, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def create(self, request):
        serializer = UserSerializer(data=request.data)

        if serializer.is_valid(raise_exception=True):
            pass

    def retrieve(self, request, pk):
        user = get_object_or_404(User, pk=pk)
        serializer = UserSerializer(user)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def get_permissions(self):
        if self.action == "list":
            permission_classes = [
                IsAdminUser,
            ]
        elif self.action == "create":
            permission_classes = [AllowAny]
        else:
            permission_classes = [AccountOwnerPermission]

        return [permission() for permission in permission_classes]
 

这是自定义权限class

class AccountOwnerPermission(permissions.BasePermission):
    def has_object_permission(self, request, view, obj):
        print(object)
        print(request.user)
        return obj == request.user

我从另一个用户访问这个视图,它向我显示用户检索,并且 2 打印在 AccountOwnerPermission 不会 运行。谁能告诉我我做的有什么问题以及为什么 has_object_permission 不会 运行.

我将 has_object_permission 更改为 has_permission 并且它有效,但另一方面我无法访问 obj

来自docs

If you're writing your own views and want to enforce object level permissions, or if you override the get_object method on a generic view, then you'll need to explicitly call the .check_object_permissions(request, obj) method on the view at the point at which you've retrieved the object.

因此您需要在 retrieve 中调用 check_object_permissions 才能触发 has_object_permission:

    def retrieve(self, request, pk):
        user = get_object_or_404(User, pk=pk)
        self.check_object_permissions(request, user) # Add this line
        serializer = UserSerializer(user)
        return Response(serializer.data, status=status.HTTP_200_OK)