Working with Django 1.4
I would like to catch an Integrity Error when a user does enter a duplicate value. At this moment the application just shows the default Django error page. (debug = True)
class Foo(models.Model):
name = models.Charfield(max_length=100, unique=True)
identifier = models.CharField(max_length=100, unique=True)
parent = models.ForeignKey("self", related_name="children")
bar = models.ForeignKey(Bar, related_name="foos")
from django.core.exceptions import ValidationError
from django.db import IntegrityError
class FooAdmin(admin.ModelAdmin):
form = FooForm
search_fields = ['name']
list_display = ['name']
def save_model(self, request, obj, form, change):
try:
obj.save()
except IntegrityError as e:
raise ValidationError(e)
class FooForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(FooForm, self).__init__(*args, **kwargs)
if self.instance.pk:
self.fields["parent"].queryset = Foo.objects.filter(bar=self.instance.bar)
def clean(self):
bar_identifier = self.cleaned_data.get("bar").identifier
parent = self.cleaned_data.get("parent")
if parent is not None:
parent_bar_identifier = parent.bar.identifier
if bar_identifier != parent_bar_identifier:
raise forms.ValidationError("Bar identifier should match parent Bar identifier")
return self.cleaded_data
At this moment I get an error page showing a ValidationError instead of an IntegrityError. (Which makes perfect sense)
How would I be able to properly catch the IntegrityError and show it at the top of the Django admin page?
I noticed there was a form in there to check if foo.parent.bar.identifier
matches foo.bar.identifier
.
When I remove the form from the ViewAdmin the error handling works as expected.
So I guess the question here would be: How do I check if the parents match when saving the admin form?
You shouldn't try to handle this in the save_model
method. The admin view expects the save_model
method to succeed, so does not handle integrity or validation errors. If the save_model
method is raising IntegrityError
, then the problem is probably somewhere else.
I think your problem is that you have forgotten to call the parent class' clean
method when you overrode it. This prevents the form from validating the unique field. See the warning in the docs for more info.
class FooForm(forms.ModelForm):
def clean(self):
cleaned_data = super(FooForm, self).clean()
parent = cleaned_data.get("parent")
...
return cleaned_data
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