Reputation: 8638
I have a model with a UniqueConstraint
:
class MyModel(models.Model)
name = models.CharField()
title = models.CharField()
class Meta:
constraints = [ models.UniqueConstraint(
fields=['name', 'title'],
name="unique_name_and_title") ]
This works fine and raises an IntegrityError
when 2 objects with the same values are created.
The problem is UniqueConstraint
doesn't present a pretty ValidationError
to the user. Usually, I would add these in the Model.clean()
class, but if I do this then it will fail on an Update
because the instance being updated will already be present:
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 How do I create a ValidationError
that passes if it's an UPDATE not an INSERT?
I know I could do this on a ModelForm
and use self.instance
to check if the instance already exists, but I want to apply this to the Model class and not have to rely on a ModelForm.
Upvotes: 3
Views: 92
Reputation: 477190
You can exclude the object from the queryset you check:
def clean(self):
qs = MyModel.objects.exclude(pk=self.pk).filter(title=self.title, name=self.name)
if qs.exists():
raise ValidationError({'title':'An object with this name+title already exists'})
return super().clean()
If the object is not yet saved, it will check for .exclude(pk=None)
, but that will not exclude any objects, since the primary key is non-nullable.
It is more efficient to use .exists()
[Django-doc] here, since it limits the bandwidth from the database to the Django/Python layer.
Upvotes: 2