Django REST (DRF) — обработка ошибок в api_view

#django #django-rest-framework

Вопрос:

У меня есть следующее представление API и сериализатор для изменения пароля пользователя:

views.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
            )
 

serializers.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"
}
 

На самом деле я ожидал бы, что в конечном итоге попаду в блок исключений APIException и получу соответствующее содержимое http, но вместо этого я получаю только http400 DRF по умолчанию, почему это? Кроме того, я бы также ожидал, что каким-то образом верну serializers.ValidationError, если таковые возникнут.

P.S. Я новичок в DRF.

Заранее спасибо

Ответ №1:

Моя ошибка, обратите внимание, что обработчик исключений будет вызываться только для ответов, сгенерированных вызванными исключениями. Он не будет использоваться для любых ответов, возвращаемых непосредственно представлением, таких как ответы HTTP_400_BAD_REQUEST, которые возвращаются общими представлениями при сбое проверки сериализатора.

пожалуйста, также смотрите: https://www.django-rest-framework.org/api-guide/exceptions/