Как переопределить метод обновления модели в django?

У меня есть модель класса, которая имеет некоторые поля, и я установил уникальные ограничения на некоторые из этих полей. Теперь мой вопрос заключается в том, что я обновляю статус некоторых классов до отмененного, что привело меня к ошибке.

duplicate key value violates unique constraint "unique-class"
DETAIL:  Key (class_id, calendar_date, is_cancelled, cancellation_count)=(6-9Hip523, 2021-10-27, t, 0) 

Я хочу пропустить эту ошибку на уровне модели. Как это сделать? Мой пользовательский метод обновления не вызывается, пожалуйста, дайте мне знать, что я делаю неправильно.

моя модель

    class Meta:
        constraints = [
            models.UniqueConstraint(fields=['class_id', 'calendar_date', 'is_cancelled', 'cancellation_count'],
                                    name='unique-class')
        ]


    def update(self, *args, **kwargs):
        if self.is_cancelled:
            try:
                super().update(*args, **kwargs)
            except:
                print("Classes are already cancelled.")

Метод .update(…) [Django-doc] предоставляется не моделью, а QuerySet. Хотя, строго говоря, вы можете переопределить его, я бы советовал не делать этого.

Вы можете переопределить метод clean() [Django-doc] или .validate_unique(…) [Django-doc] и вызвать ошибку валидации. Если вы затем используете ModelForm, ModelAdmin или ModelSerializer, то будет показана соответствующая ошибка.

Таким образом, мы можем реализовать это в модели следующим образом:

from django.core.exceptions import ValidationError

class MyModel(models.Model):

    def validate_unique(self, *args, **kwargs):
        qs = MyModel.objects.exclude(pk=self.pk).filter(
            class_id=self.class_id,
            calendar_date=self.calendar_date,
            is_cancelled=self.is_cancelled,
            cancellation_count=self.cancellation_count
        ).exists()
        if qs:
            raise ValidationError('Classes are already cancelled')
        return super().validate_unique(*args, **kwargs)

    class Meta:
        # …
        pass

Если вы обновляете его через Django ORM, то он не будет выполнять валидацию. В этом случае вы можете попытаться обновить объект и поймать исключение, так:

from django.db.utils import IntegrityError

try:
    MyModel.objects.filter(…).update(…)
except IntegrityError:
    # …
    # do something
    pass
Вернуться на верх