Как проверить уникальность в функции Model.clean ()? - PullRequest
3 голосов
/ 12 июля 2020

У меня есть модель с UniqueConstraint:

class MyModel(models.Model)
    name = models.CharField()
    title = models.CharField()
  
    class Meta:
        constraints = [ models.UniqueConstraint(
                          fields=['name', 'title'],
                          name="unique_name_and_title") ]

Это отлично работает и вызывает IntegrityError, когда создаются 2 объекта с одинаковыми значениями.

Проблема в том, что UniqueConstraint не дает пользователю красивого ValidationError. Обычно я добавляю их в класс Model.clean(), но если я это сделаю, он не будет работать на Update, потому что обновляемый экземпляр уже будет присутствовать:

def clean(self):
    if MyModel.objects.filter(title=self.title, name=self.name):
             raise ValidationError({'title':'An object with this name+title already exists'})

I Как мне создать ValidationError, который проходит, если это ОБНОВЛЕНИЕ, а не ВСТАВКА?

Я знаю, что могу сделать это на ModelForm и использовать self.instance, чтобы проверить, существует ли уже экземпляр, но я хочу применить это в класс Model и не нужно полагаться на ModelForm.

1 Ответ

2 голосов
/ 12 июля 2020

Вы можете исключить объект из проверяемого набора запросов:

def clean(self):
    qs = MyModel.objects.<b>exclude(pk=self.pk)</b>.filter(title=self.title, name=self.name)
    if qs.<b>exists()</b>:
        raise ValidationError({'title':'An object with this name+title already exists'})
    return super().clean()

Если объект еще не сохранен, он проверит наличие .exclude(pk=None), но это не будет исключать какие-либо объекты, поскольку первичный ключ не допускает значения NULL.

Более эффективно использовать здесь .exists() [Django -doc] , поскольку это ограничивает пропускную способность из базы данных на слой Django / Python.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...