【问题标题】:Django REST Framework ValidationError always returns 400Django REST Framework ValidationError 总是返回 400
【发布时间】:2019-01-05 01:24:52
【问题描述】:

我正在尝试强制 ValidationError 返回与 400 不同的状态码。这就是我所做的:

class MyValidationError(ValidationError):
    status_code = HTTP_403_FORBIDDEN

然后在序列化器中:

def validate_field(self, value):
    raise MyValidationError

为什么我在这里得到 400 而不是 403?有趣的是,如果我使用 PermissionDenied 和自定义状态代码(我尝试了 204)而不是 ValidationError,它会按预期工作。

【问题讨论】:

    标签: django-rest-framework http-status-codes serialization


    【解决方案1】:

    Django RestFramework 序列化程序验证所有可能的字段并最终返回错误集。

    也就是说,假设您期望序列化程序中有两个验证错误,其中一个验证错误是由MyValidationError 引发的。在那种情况下,DRF 显然会返回 HTTP 400 状态码,因为 DRF 的 设计模式 不会引发 individual 验证错误。

    序列化验证过程在is_valid() 方法内部完成,并在方法结束时引发 ValidationError。

    def is_valid(self, raise_exception=False):
        ....code
        ....code
        if self._errors and raise_exception:
            raise ValidationError(self.errors)
    
        return not bool(self._errors)

    ValidationError 类引发 HTTP 400

    class ValidationError(APIException):
        status_code = status.HTTP_400_BAD_REQUEST
        default_detail = _('Invalid input.')
        default_code = 'invalid'
        .... code


    为什么 PermissionDenaid 返回自定义状态码?

    在is_valid() (source code) 方法中,它只捕获ValidationError

    if not hasattr(self, '_validated_data'):
        try:
            self._validated_data = self.run_validation(self.initial_data)
        except ValidationError as exc:
            self._validated_data = {}
            self._errors = exc.detail
        else:
            self._errors = {}
    到时候DRF直接抛出PermissionDenaid异常,返回自己的状态码,由你自定义


    结论

    DRF Serializer ValidationError 永远不会返回除HTTP 400 之外的状态代码,因为它捕获其他子验证错误异常(如果有)并且最后提出了一个主要的ValidationError,它通过它的设计模式返回HTTP 400状态码

    参考:
    is_valid() source code
    ValidationError class source code

    【讨论】:

      【解决方案2】:

      你只需创建自己的异常类并在序列化程序中重新引发它

      class ValidationError422(APIException):
          status_code = status.HTTP_422_UNPROCESSABLE_ENTITY
      
      
      class BusinessSerializer(serializers.ModelSerializer):
          class Meta:
              model = Business
              fields = ('id', 'name')
      
          def is_valid(self, raise_exception=False):
              try:
                  return super(BusinessSerializer, self).is_valid(raise_exception)
              except ValidationError as e:
                  raise ValidationError422(detail=e.detail)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-31
        • 1970-01-01
        • 2018-12-22
        • 1970-01-01
        • 2019-08-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多