2014-02-21 54 views
4

对于我的一个模型,我需要确保某些行的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'),) 
+3

使用'unique_together'通过发出'UNIQUE'语句不是在django级别在db级别强制执行;它看起来不像(至少mysql)支持条件唯一。你可以在应用程序级别实现你想要的行为 – dm03514

回答

7

你不能做到这一点与在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

除了前面的回答,您可以使用递归。这将是这样的:

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()方法。