Reputation: 447
I have a class model which has some fields and I have put up unique constraints on some of those fields. Now my query is I am updating some of my classes status to cancelled, that led me to the error.
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)
I want to skip this error on model level. How to do that? My custom update method is not getting called, please let me know what I am doing wrong here.
my model
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.")
Upvotes: 1
Views: 2686
Reputation: 477607
The .update(…)
method [Django-doc] is is not provided by the model, but by the QuerySet
. While you can strictly speaking override that, I would advise not to do this.
What you can do is override the clean()
method [Django-doc] or .validate_unique(…)
[Django-doc] and raise a validation error. If you then use a ModelForm
, ModelAdmin
, or ModelSerializer
, it will show the corresponding error.
We thus can implement this in the model with:
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
If you update it through the Django ORM, then it will not perform validation. In that case you can try to update the object, and catch the exception, so:
from django.db.utils import IntegrityError
try:
MyModel.objects.filter(…).update(…)
except IntegrityError:
# …
# do something
pass
Upvotes: 1