首页 > 解决方案 > Django REST (DRF) - api_view 中的错误处理

问题描述

我有以下 API 视图和序列化程序来更改用户密码:

视图.py

@api_view(['POST'])
@permission_classes([AllowAny])
def user_create(request):
    exception_handler = UserUnavailable
    success_handler = UserCreated
    if request.method == 'POST':
        creation_serializer = UserCreateSerializer(data=request.data)
        try:
            if creation_serializer.is_valid(raise_exception=True):
                creation_serializer.save()
                user_serializer = NewUserSerializer(instance=creation_serializer.instance)
                return JsonResponse(
                    {"status_code": success_handler.status_code,
                     "default_detail": success_handler.default_detail,
                     "default_code": success_handler.default_code,
                     "new_user": user_serializer.data,
                     }, status=status.HTTP_201_CREATED, safe=False)

        except APIException:
            return Response(
                {"status_code": exception_handler.status_code,
                 "default_detail": exception_handler.default_detail,
                 "default_code": exception_handler.default_code},
                status=status.HTTP_400_BAD_REQUEST
            )

序列化程序.py

class UserPasswordSerializer(serializers.ModelSerializer):
    user = serializers.PrimaryKeyRelatedField(read_only=True, default=serializers.CurrentUserDefault())
    password = serializers.CharField(max_length=128, write_only=True, required=True, validators=[validate_password])
    password2 = serializers.CharField(max_length=128, required=True)
    old_password = serializers.CharField(max_length=128, required=True)

    class Meta:
        model = get_user_model()
        fields = ('user', 'password', 'password2', 'old_password')
        extra_kwargs = {'password': {'write_only': True}}

    def validate_old_password(self, value):
        user = self.context['request'].user
        if not user.check_password(value):
            raise serializers.ValidationError(
                ({'old_password': _("Your old password was entered incorrectly. Please enter it again..")})
            )
        return value

    def validate(self, data):
        if data['password'] != data['password2']:
            raise serializers.ValidationError({'password2': _("The two password fields didn't match.")})
        password_validation.validate_password(data['password'])
        return data

    def save(self, **kwargs):
        password = self.validated_data['password']
        user = self.context['request'].user
        user.set_password(password)
        user.save()
        return user

如果我更新用户密码,我只需返回 http200 并设置密码,很好!但是,如果我第二次发送相同的请求,我就会回来:

{
  "status": "error",
  "error": "Bad Request"
}

实际上,我希望在 except APIException 块中结束并返回相应的 http 内容,但我只得到 DRF 的默认 http400,为什么呢?除此之外,我还希望以某种方式获得 serializers.ValidationError 如果发生任何情况。

PS我是DRF的新手。

提前致谢

标签: djangodjango-rest-framework

解决方案


我的错,请注意,异常处理程序只会被引发的异常生成的响应调用。它不会用于视图直接返回的任何响应,例如当序列化验证失败时通用视图返回的 HTTP_400_BAD_REQUEST 响应。

另请参阅:https ://www.django-rest-framework.org/api-guide/exceptions/


推荐阅读