Django模型字段validation
模型字段的validation应该在django中进行?
我可以命名至less两个可能的select:在模型的重载.save()方法或models.Field子类的.to_python()方法中(显然是为了工作,您必须编写自定义字段)。
可能的用例:
- 当绝对需要确保空string不会写入数据库时(空白= False关键字参数在这里不起作用,仅用于表单validation)
- 当需要确保时,“select”关键字参数在数据库级别上得到了尊重,而不仅仅在pipe理接口(类似于模拟枚举数据types)
在models.Field基类定义和派生类中也有一个类级属性empty_strings_allowed
,但它似乎并没有对数据库级别产生任何影响,这意味着我仍然可以用空string构造一个模型字段并将其保存到数据库。 我想避免(是的,这是必要的)。
可能的实现是
在现场层面:
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就有了一个模型validation系统。
在注释sebpiq中说:“好了,现在有一个地方可以放置模型validation…除了它只在使用ModelForm时运行!所以问题依然存在,当需要确保validation在db级别,你应该怎么做?在哪里打电话给full_clean?
通过Python级别的validation是不可能的,以确保validation是在数据库级别。 最接近的可能是在重写的save
方法中调用full_clean
。 这不是默认情况下完成的,因为这意味着每个调用save方法的人现在都可以更好地捕获和处理ValidationError
。
但即使你这样做了,有人仍然可以使用queryset.update()
批量更新模型实例,这将绕过这个validation。 Django没有办法实现合理高效的queryset.update()
,它仍然可以在每个更新的对象上执行Python级别的validation。
真正保证数据库级别完整性的唯一方法是通过数据库级别的限制; 您通过ORM进行的任何validation都要求应用程序代码编写者了解何时执行validation(并处理validation失败)。
这就是为什么模型validation默认只在ModelForm
执行的ModelForm
– 因为在ModelForm中已经有了一个明显的方法来处理ValidationError
。
我想你想要这个 – >
from django.db.models.signals import pre_save def validate_model(sender, **kwargs): if 'raw' in kwargs and not kwargs['raw']: kwargs['instance'].full_clean() pre_save.connect(validate_model, dispatch_uid='validate_models')
这个问题的根本问题是validation应该发生在模型上。 这已经在django(开发邮件列表中的search表单模型感知validation)中讨论了相当长的一段时间。 它会导致重复或事件之前击中数据库的validation。
虽然这不是主干,但马尔科姆的“穷人的模型validation解决scheme”可能是避免重复自己的最干净的解决scheme。
如果我理解你“清楚” – 你必须覆盖函数get_db_prep_save而不是to_python