Django rest框架在自己验证之前进行模型字段验证

时间:2016-10-26 14:44:30

标签: validation django-rest-framework

我不了解django休息框架验证过程。 doc say验证完全在序列化程序类上执行。

然而, 对于模型中的PositiveIntegerField,当ModelSerializer收到负值时,将在自定义ModelSerializer validate_myfield方法之前处理模型验证。

class Blop(models.Model):
    quantity = models.PositiveSmallIntegerField()

class BlopSerializer(serializers.ModelSerializer):
    def validate_quantity(self, value):
        return max(15, value)

    class Meta:
        model = Blop

如果数量小于零,则永远不会调用validate_quantity ...

我也尝试过:

  • 使用型号"清洁"方法,但休息框架不使用它。
  • 通过将min_value设置为None来禁用模型中的min值验证器,但它会使rest框架崩溃
  • 在模型字段中强制使用MinValueValidator:validators=[MinValueValidator(-math.inf, 'Minimum value is -Infinity')],它有效,但它太难看了

在这种情况下,如何让序列化程序确保非负值?

1 个答案:

答案 0 :(得分:2)

我认为您的问题是您调用的serializer.is_valid()方法没有kwargs或raise_exception=False。 使用raise_exception=True,如果传递无效数据,序列化程序会引发ValidationError

为了更好地理解,让我们看一下Serializer.to_internal_value方法。

def to_internal_value(self, data):
    """
    Dict of native values <- Dict of primitive datatypes.
    """
    if not isinstance(data, dict):
        message = self.error_messages['invalid'].format(
            datatype=type(data).__name__
        )
        raise ValidationError({
            api_settings.NON_FIELD_ERRORS_KEY: [message]
        })

    ret = OrderedDict()
    errors = OrderedDict()
    fields = self._writable_fields

    for field in fields:
        validate_method = getattr(self, 'validate_' + field.field_name, None)
        primitive_value = field.get_value(data)
        try:
            validated_value = field.run_validation(primitive_value)
            if validate_method is not None:
                validated_value = validate_method(validated_value)
        except ValidationError as exc:
            errors[field.field_name] = exc.detail
        except DjangoValidationError as exc:
            errors[field.field_name] = list(exc.messages)
        except SkipField:
            pass
        else:
            set_value(ret, field.source_attrs, validated_value)

    if errors:
        raise ValidationError(errors)

    return ret

正如您在此处所看到的,首先,序列化程序调用{​​{1}}方法,该方法使用django-fields验证器并引发field.run_validation异常,因此,您的验证方法永远不会被调用。 / p>