Django的model.full_clean()允许IntegerField

问题描述:

无效值我有一个继承了一些模型,看起来像这样:Django的model.full_clean()允许IntegerField

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)]) 

然后我火了Django的外壳并执行以下操作:

>>> obj = B() 
>>> obj.some_text = 'foo' 
>>> obj.some_int = 'bar' 
>>> obj.full_clean() 

,自然我得到:

>>> ValidationError: {'some_int': [u"'bar' value must be an integer."]} 

好。然后:

>>> obj.some_int = ' ' #whitespace 
>>> obj.full_clean() 

我也得到:

>>> ValidationError: {'some_int': [u"' ' value must be an integer."]} 

完美。但后来我尝试空字符串:

>>> obj.some_int = '' #empty string 
>>> obj.full_clean() 

没有ValidationError提高,但如果我尝试保存对象:

>>> obj.save() 

我得到:

>>> ValueError: invalid literal for int() with base 10: '' 

这是怎么回事?这是正确的行为? Django如何检查值是否为有效整数?

我真的不想自定义我的模型的clean()函数来检查这个,但它开始看起来像我没有选择。

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

的这种现象的原因是在评价方法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) 
+0

Welp ...你说得对。我想这有一个很好的理由,我目前无法完全理解。尽管如此,看到它明确写道我负责验证空白字段的'blank = True'使得解决方案感觉不那么脏乱。谢谢。 – 2014-08-31 21:32:34

那是因为你允许你的字段为空(也是空)。 所以它是好的,它是有效的。

如果你不希望它是这样,只是删除blank=True选项,或将其更改为blank=False

+2

如果“它是好的,它是有效的”,那么为什么一个异常升高,当我尝试保存对象?如果我将该值设置为无,它工作正常。当我调用save_()时调用full_clean()并且没有值错误时,它不会引发验证错误。这只发生在一个空字符串。 – 2014-08-31 21:17:45

,因为你有blank=True你得到此行为。我同意你的看法,你看到的行为很奇怪 - 这是Django 模型验证与表单验证绑定的事实的一个症状,即使原则上它们可以是分开的。

假设你实际上需要blank=Truenull=True,我不会担心这个。表单将做正确的事情(将表单中的空字符串转换为数据库中的NULL值),并且模型和数据库实际上不会让您保存无效值。唯一的问题是,如果您有不涉及Django表单的数据输入,则错误将被抛出save()时间,而不是在full_clean()时间。

当然,如果您不想允许该字段的值为NULL,只需设置blank=False, null=Falsefull_clean()就会像您期望的那样抱怨空字符串。

+0

不幸的是,该字段必须保持为'blank = False,null = False'...并且我确实有不涉及Django表单的数据输入。看起来我必须自己检查一下。感谢您的见解。 – 2014-08-31 21:28:49