如何使用 DRF APIView get 方法和 ModelSerializer 返回 400 状态代码?

Jus*_*ing 3 validation http-status-codes django-rest-framework

我有以下代码(对于端点 /things/{id}/permission-to-do/views.py

class PermissionsToDo(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)
    def get(self, request,*args,**kwargs):
        thing_id = kwargs.get('pk')
        thing = Thing.objects.filter(pk=thing_id,is_active=True)
        serializer = serializers.GetDoPermissionSerializer(thing[0],context={'request': request})
        return Response(serializer.data, status=status.HTTP_200_OK)
Run Code Online (Sandbox Code Playgroud)

序列化程序.py

class serializers.GetDoPermissionSerializer(serializers.ModelSerializer):
    def _can_do(self, thing):
        return thing.can_be_done_by(self.context['request'].user)

    can_do = serializers.SerializerMethodField('_can_do')

    class Meta:
        model = Thing.objects.filter
        fields = ('can_do',)
        extra_kwargs = {
            'can_do': {'read_only': True},
        }
Run Code Online (Sandbox Code Playgroud)

thing.can_be_done_by(user)方法返回一个布尔值。这适用于正确的请求,但我想添加一种方法来验证请求并为客户端错误发送适当的状态代码,例如status.HTTP_400_BAD_REQUEST

我的想法是在views.py 中添加一个:

if serializer.is_valid():
    return Response(serializer.data, status=status.HTTP_200_OK)
else:
    return Response(SOMETHING?,status.HTTP_400_BAD_REQUEST)
Run Code Online (Sandbox Code Playgroud)

如果我进行评估,serializer.is_valid()我会收到一条错误消息:

'Cannot call `.is_valid()` as no `data=` keyword argument was '
AssertionError: Cannot call `.is_valid()` as no `data=` keyword argument was passed when instantiating the serializer instance. 
Run Code Online (Sandbox Code Playgroud)

如果我改变行:

serializer = serializers.GetDoPermissionSerializer(thing[0],context={'request': request})
Run Code Online (Sandbox Code Playgroud)

进入:

serializer = serializers.GetDoPermissionSerializer(data=thing[0],context={'request': request})
Run Code Online (Sandbox Code Playgroud)

但是然后,我收到一个错误,提示我应该将字典作为数据而不是对象传递。但是我不确定如何实现该validate方法以及如何更改该_can_do方法以使其正常工作。

任何的想法?

如果您有空闲时间,感谢您的时间!

JPG*_*JPG 6

.validate()方法接受一个参数,它是一个字段值的字典。如有必要,它应该引发 ValidationError,或者只返回经过验证的值。
实现此目的的方法之一是将 转换model objectdict. 所以试试下面的代码片段,

class PermissionsToDo(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)

    def get(self, request, *args, **kwargs):
        thing_id = kwargs.get('pk')
        thing = Thing.objects.filter(pk=thing_id, is_active=True)
        serializer = serializers.GetDoPermissionSerializer(data=thing[0].__dict__, context={'request': request})  # Change is here <<<<
        if serializer.is_valid():
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(SOMETHING?, status.HTTP_400_BAD_REQUEST)
Run Code Online (Sandbox Code Playgroud)


我的建议

如果您从 DB 序列化对象,大多数情况下它不会引发任何验证错误。我建议,如果thing对象变成empty queryset.So,请尝试显示错误消息,

class PermissionsToDo(APIView):
    authentication_classes = (TokenAuthentication,)
    permission_classes = (IsAuthenticated,)

    def get(self, request, *args, **kwargs):
        thing_id = kwargs.get('pk')
        try:
            serializer = serializers.GetDoPermissionSerializer(Thing.objects.get(id=thing_id), context={'request': request})
            return Response(serializer.data, status=status.HTTP_200_OK)
        except Thing.DoesNotExist:
            return Response(data="object not found", status.HTTP_400_BAD_REQUEST)
Run Code Online (Sandbox Code Playgroud)