2014-02-21 3 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' применяется на уровне db, выдавая инструкцию' UNIQUE' не на уровне django; он не похож (по крайней мере, mysql) поддерживает условный уникальный. Вы можете реализовать желаемое поведение на уровне приложения – dm03514

ответ

7

Вы не можете сделать это с помощью unique_together в Django, по-видимому, потому что не все дБ движки бы быть в состоянии поддерживать его.

Вы можете сделать это на уровне приложений с моделью проверки вместо:
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().

Смежные вопросы