模型字段 的验证在django中应该去哪里?
我可以至少命名两个可能的选择:在模型的重载.save()方法中或在模型.field_子类的.to_python()方法中(显然,要工作,您必须编写自定义字段)。
可能的用例:
模型中还有一个类级别的属性。字段empty_strings_allowed基类定义和派生类很高兴地覆盖它,但是它似乎对数据库级别没有任何影响,这意味着我仍然可以使用空字符串字段构建模型并将其保存到数据库。我要避免的(是,这是必要的)。
empty_strings_allowed
可能的实现方式是
在现场一级:
class CustomField(models.CharField): __metaclass__ = models.SubfieldBase def to_python(self, value): if not value: raise IntegrityError(_('Empty string not allowed')) return models.CharField.to_python(self, value)
在模型级别:
class MyModel(models.Model) FIELD1_CHOICES = ['foo', 'bar', 'baz'] field1 = models.CharField(max_length=255, choices=[(item,item) for item in FIELD1_CHOICES]) def save(self, force_insert=False, force_update=False): if self.field1 not in MyModel.FIELD1_CHOICES: raise IntegrityError(_('Invalid value of field1')) # this can, of course, be made more generic models.Model.save(self, force_insert, force_update)
也许,我缺少了一些东西,而且可以做得更容易(更清洁)?
自版本1.2起,Django已有模型验证系统。
sebpiq在评论中说:“好吧,现在有地方放置模型验证了……除了仅在使用ModelForm时才运行模型验证!因此问题仍然存在,何时有必要确保在数据库级尊重验证,该怎么办?在哪里调用full_clean?”
无法通过Python级别的验证来确保在db级别上遵守验证。最接近的可能是调用full_clean重写的save方法。默认情况下不会执行此操作,因为这意味着每个调用该save方法的人现在最好都准备好捕获和处理ValidationError。
full_clean
save
ValidationError
但是即使您执行此操作,仍然有人可以使用来批量更新模型实例queryset.update(),这将绕过此验证。Django无法实现一种合理有效的方法queryset.update(),该方法仍然可以对每个更新的对象执行Python级别的验证。
queryset.update()
真正保证数据库级完整性的唯一方法是通过数据库级约束。您通过ORM进行的任何验证都要求应用程序代码的编写者知道何时执行验证(并处理验证失败)。
这就是为什么默认情况下仅在in中强制执行模型验证的ModelForm原因,因为在ModelForm中已经存在一种明显的方法来处理ValidationError。
ModelForm