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)
那是因为你允许你的字段为空(也是空)。 所以它是好的,它是有效的。
如果你不希望它是这样,只是删除blank=True
选项,或将其更改为blank=False
如果“它是好的,它是有效的”,那么为什么一个异常升高,当我尝试保存对象?如果我将该值设置为无,它工作正常。当我调用save_()时调用full_clean()并且没有值错误时,它不会引发验证错误。这只发生在一个空字符串。 – 2014-08-31 21:17:45
,因为你有blank=True
你得到此行为。我同意你的看法,你看到的行为很奇怪 - 这是Django 模型验证与表单验证绑定的事实的一个症状,即使原则上它们可以是分开的。
假设你实际上需要blank=True
和null=True
,我不会担心这个。表单将做正确的事情(将表单中的空字符串转换为数据库中的NULL
值),并且模型和数据库实际上不会让您保存无效值。唯一的问题是,如果您有不涉及Django表单的数据输入,则错误将被抛出save()
时间,而不是在full_clean()
时间。
当然,如果您不想允许该字段的值为NULL
,只需设置blank=False, null=False
和full_clean()
就会像您期望的那样抱怨空字符串。
不幸的是,该字段必须保持为'blank = False,null = False'...并且我确实有不涉及Django表单的数据输入。看起来我必须自己检查一下。感谢您的见解。 – 2014-08-31 21:28:49
Welp ...你说得对。我想这有一个很好的理由,我目前无法完全理解。尽管如此,看到它明确写道我负责验证空白字段的'blank = True'使得解决方案感觉不那么脏乱。谢谢。 – 2014-08-31 21:32:34