对于我的一个模型,我需要确保某些行的unicity,但仅限于某些情况。只有“已验证”的行才能遵循此约束。
基本上,我期待像
这样的东西class MyModel(models.Model):
field_a = models.CharField()
field_b = models.CharField()
validated = models.BooleanField(default=False)
class Meta:
unique_together = (('field_a', 'field_b', 'validated=True'),)
答案 0 :(得分:9)
您无法在Django中使用unique_together
执行此操作,大概是因为并非所有数据库后端都能够支持它。
您可以使用模型验证在应用程序层中执行此操作:
https://docs.djangoproject.com/en/dev/ref/models/instances/#validating-objects
例如
class MyModel(models.Model):
field_a = models.CharField()
field_b = models.CharField()
validated = models.BooleanField(default=False)
def clean(self):
if not self.validated:
return
existing = self.__class__.objects.filter(field_a=self.field_a,
field_b=self.field_b).count()
if existing > 0:
raise ValidationError(
"field_a and field_b must be unique if validated=True"
)
请注意,您可能需要手动调用模型验证,即
instance.clean()
instance.save()
保存模型时不会自动完成。另一方面,当使用ModelForm时, 自动完成,即
if form.is_valid():
instance = form.save()
答案 1 :(得分:1)
除了上一个答案,您还可以使用递归。它会是这样的:
def save(self, **kwargs):
try:
self.objects.get(field_a=self.field_a, field_b=self.field_b, validated=True)
# this wont run if the previous line throw an exception
raise ValidationError(
"field_a and field_b must be unique if validated=True"
)
except self.__class__.DoesNotExist: # does not catch the ValidationError
super(MyModel, self).save(**kwargs) # everything cool
现在您不需要调用clean()
方法。
答案 2 :(得分:1)
如果您使用的是Django 2.2+,则可以使用UniqueConstraint 这是一个示例
class MyModel(models.Model):
field_a = models.CharField()
field_b = models.CharField()
validated = models.BooleanField(default=False)
class Meta:
constraints = [
UniqueConstraint(fields=['field_a', 'field_b'], condition=Q(validated=True), name='unique_field_a_field_b_validated')
]
这是source