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

(从http://djangosnippets.org/snippets/2319/复制);

这个问题的根本问题是validation应该发生在模型上。 这已经在django(开发邮件列表中的search表单模型感知validation)中讨论了相当长的一段时间。 它会导致重复或事件之前击中数据库的validation。

虽然这不是主干,但马尔科姆的“穷人的模型validation解决scheme”可能是避免重复自己的最干净的解决scheme。

如果我理解你“清楚” – 你必须覆盖函数get_db_prep_save而不是to_python