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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With