Django model.full_clean()允许IntegerField的值无效

Arm*_*ado 2 django django-models django-validation

我有一些带有继承的模型,看起来像这样:

Class A(models.Model):
    some_text = models.CharField(max_length=100)
    #other fields, not important

Class B(A):
    some_int = models.IntegerField(blank=True, null=True, validators=[MinValueValidator(1), MaxValueValidator(1000)])
Run Code Online (Sandbox Code Playgroud)

然后我启动Django shell并执行以下操作:

>>> obj = B()
>>> obj.some_text = 'foo'
>>> obj.some_int = 'bar'
>>> obj.full_clean()
Run Code Online (Sandbox Code Playgroud)

我自然得到:

>>> ValidationError: {'some_int': [u"'bar' value must be an integer."]}
Run Code Online (Sandbox Code Playgroud)

好。然后:

>>> obj.some_int = '   ' #whitespace
>>> obj.full_clean()
Run Code Online (Sandbox Code Playgroud)

我得到:

>>> ValidationError: {'some_int': [u"'   ' value must be an integer."]}
Run Code Online (Sandbox Code Playgroud)

完善。但是,然后我尝试一个空字符串:

>>> obj.some_int = '' #empty string
>>> obj.full_clean()
Run Code Online (Sandbox Code Playgroud)

没有引发ValidationError,但是如果我尝试保存对象:

>>> obj.save()
Run Code Online (Sandbox Code Playgroud)

我得到:

>>> ValueError: invalid literal for int() with base 10: ''
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?这是正确的行为吗?Django如何检查值是否为有效整数?

我真的不想自定义模型的clean()函数来检查这一点,但是看起来好像别无选择。

编辑:Django 1.6.5,Python 2.7.6,Windows 7 64位。

Has*_*ani 5

在clean_fields方法中注释了此行为的原因:

    def clean_fields(self, exclude=None):
    """
    Cleans all fields and raises a ValidationError containing message_dict
    of all validation errors if any occur.
    """
    if exclude is None:
        exclude = []

    errors = {}
    for f in self._meta.fields:
        if f.name in exclude:
            continue
        # Skip validation for empty fields with blank=True. The developer
        # is responsible for making sure they have a valid value.
        raw_value = getattr(self, f.attname)
        if f.blank and raw_value in f.empty_values:
            continue
        try:
            setattr(self, f.attname, f.clean(raw_value, self))
        except ValidationError as e:
            errors[f.name] = e.error_list

    if errors:
        raise ValidationError(errors)
Run Code Online (Sandbox Code Playgroud)