使用 CreateAPIView 检查对象权限

den*_*aar 3 django django-rest-framework

CommentCreateCreateAPIView用于在另一个“报告”模型上发表评论。我需要阻止任何不是报告作者的人,或者不在允许发表评论的指定人群中的任何人使用此端点创建评论。

class CommentCreate(generics.CreateAPIView):
    serializer_class = CommentSerializer
    queryset = Comment.objects.none()

    def check_object_permissions(self, request, obj):
        if obj.report.creator != request.user:
            # also check if request.user is in the group of people that can comment
            raise exceptions.PermissionDenied(
                detail='You do not have permission')
Run Code Online (Sandbox Code Playgroud)

我面临的问题是它check_object_permissions被调用了,但在任何地方都没有捕获异常,因此无论如何都会正常发布评论。我在这里缺少什么?

Dan*_*tar 6

创建check_object_permissionsa 时不会调用该方法Comment

这是完整的create代码CreateAPIView

class CreateModelMixin(object):
    """
    Create a model instance.
    """
    def create(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

    def perform_create(self, serializer):
        serializer.save()

    def get_success_headers(self, data):
        try:
            return {'Location': data[api_settings.URL_FIELD_NAME]}
        except (TypeError, KeyError):
            return {}
Run Code Online (Sandbox Code Playgroud)

check_object_permissions只名为中get_object,当您尝试检索对象VIE API本身只调用。

为了进行权限检查,CommentCreate您应该覆盖perform_create那里的方法并进行检查:

class CommentCreate(generics.CreateAPIView):
    serializer_class = CommentSerializer
    queryset = Comment.objects.none()

    def perform_create(self, serializer):
        # untested if...
        if serializer.validated_data['report'].creator != self.request.user:
            raise exceptions.PermissionDenied(
                detail='You do not have permission')

        serializer.save()
Run Code Online (Sandbox Code Playgroud)

  • 我需要提到的是,在perform_create内部你不能再访问serializer.data。您只能在serializer.save()之前访问serializer.validated_data。请修正你的答案:D (2认同)