Model.clean
通常在Model.clean [Django-doc] 中编写此类测试:
from django.core.exceptions import ValidationError
class Person(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
field1= models.IntegerField(null=True)
field2 = models.IntegerField(null=True)
def clean(self):
super().clean()
if self.field1 is None and self.field2 is None:
raise ValidationError('Field1 or field2 are both None')
请注意,当您.save() 模型时,默认情况下不验证此 clean 方法。它通常仅由构建在此模型之上的ModelForms 调用。当您 .save() 模型实例时,您可以修补 .save() 方法 for example like here 以强制验证,但仍有一些方法可以通过 ORM规避。
django-db-constraints(部分数据库不支持)
如果您的数据库支持它(例如 MySQL simply ignores the CHECK constraints),SQL 提供了一种语法来添加额外的约束,而 Django 包 django-db-constraints [GitHub] 提供了一些工具来指定此类约束,例如:
class Person(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
field1= models.IntegerField(null=True)
field2 = models.IntegerField(null=True)
class Meta:
db_constraints = {
'field_null': 'CHECK (field1 IS NOT NULL OR field2 IS NOT NULL)',
}
更新:Django 约束框架
由于django-2.2,您可以使用Django constraint framework [Django-doc]。使用此框架,您可以指定数据库约束,如果数据库支持这一点,则在数据库端进行验证。因此,您可以检查两个字段中的至少一个是否不是NULL 和CheckConstraint [Django-doc]:
class Person(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
field1= models.IntegerField(null=True)
field2 = models.IntegerField(null=True)
class Meta:
constraints = [
models.CheckConstraint(
check=Q(field1__isnull=False) | Q(field2__isnull=False),
name='not_both_null'
)
]