In my django powered app there is only one obvious case where "IntegrityError" can arise.
So, how can I catch that error and display a message using templates?

- 8,084
- 8
- 48
- 62

- 3,834
- 5
- 45
- 63
8 Answers
Just use try and catch.
from django.db import IntegrityError
from django.shortcuts import render_to_response
try:
# code that produces error
except IntegrityError as e:
return render_to_response("template.html", {"message": e.message})
If you want you can use the message in your template.
EDIT
Thanks for Jill-Jênn Vie, you should use e.__cause__
, as described here.
-
Thanks, I couldn't figure out why "from MySQLdb import IntegrityError" wasn't doing the trick. The call stack seemed to show that was the library raising the error, yet it somehow gets moved to django.db. Grr. – Julian Nov 06 '13 at 19:33
-
5As pointed out in the [docs of v1.6](https://docs.djangoproject.com/en/1.6/ref/exceptions/#database-exceptions), `e.__cause__` is preferred, as per [PEP 3134](http://legacy.python.org/dev/peps/pep-3134/). – Jill-Jênn Vie Aug 06 '14 at 19:42
-
2If you don't get message, try this : e.args – Jay Modi Feb 29 '16 at 06:51
-
e.message did not work for me, but e.args[1] did do the job – Edgar Navasardyan May 15 '16 at 09:37
-
@blissini - I've changed the link to point to the dev documentation – Tony Sep 26 '16 at 13:10
-
Does doing a try/catch slow things down? – natab Dec 21 '16 at 21:15
-
No. There are very few cases where try-catch will slow things down. – Joe Dec 22 '16 at 09:24
-
@EdgarNavasardyan, were you passing other values to `IntegrityError`? the expression `IntegrityError('some message')` has `some message` at `e.args[0]`. – lsh Jan 15 '17 at 12:20
If you're using class-based views with the CreateView
mixin, you'll want to try
the call to the superclass's form_valid
, for example:
from django.db import IntegrityError
...
class KumquatCreateView(CreateView):
model = Kumquat
form_class = forms.KumquatForm
...
def form_valid(self, form):
...
try:
return super(KumquatCreateView, self).form_valid(form)
except IntegrityError:
return HttpResponse("ERROR: Kumquat already exists!")
You can use a template, render_to_response
etc. to make the output nicer, of course.

- 1,952
- 2
- 17
- 28

- 3,025
- 4
- 28
- 28
I would validate it with ModelForm. For example:
You got model:
class Manufacturer(models.Model):
name = models.CharField(default='', max_length=40, unique=True)
And ModelForm:
class ManufacturerForm(forms.ModelForm):
def clean(self):
cleaned_data = super(ManufacturerForm, self).clean()
name = cleaned_data.get('name')
if Manufacturer.objects.filter(name=name).exists():
raise forms.ValidationError('Category already exists')
class Meta:
model = Manufacturer
In this case when you submit name that is unique. You'll get validation error before IntegrityError. 'Category already exists' message will be shown in your form in template

- 41
- 4
Simplest solution: write a middleware implementing process_exception
that only catches IntegrityError and returns an HttpResponse with your rendered template, and make sure this middleware is after the default error handling middleware so it is called before (cf https://docs.djangoproject.com/en/dev/topics/http/middleware/#process-exception for more).
Now if I was you, I wouldn't assume such a thing as "there is only one obvious case where "IntegrityError" can arise", so I strongly recommand you do log the exception (and send email alerts) in your middleware.

- 9,672
- 3
- 47
- 75

- 75,974
- 6
- 88
- 118
-
Putting it in middleware will not just catch the Error in the app, but in all apps in the project. – Chris Wesseling Jul 02 '12 at 12:28
-
@ChrisWesseling: Totally agree, that's why I mentionned that "I wouldn't assume such a thing as "there is only one obvious case where "IntegrityError" can arise"" – bruno desthuilliers Jul 02 '12 at 12:30
-
1Guns don't shoot people in the foot, people shoot people in the foot. :-) – Chris Wesseling Jul 02 '12 at 12:32
-
I wouldn't call it the simplest solution but it is a useful alternative to know about. Thanks. – spinkus Aug 02 '16 at 03:34
I did it like this
from django.db import IntegrityError
from django.shortcuts import render
from .models import Person
from .forms import PersonForm
class PersonView(View):
def get(self, request):
pd = PersonForm()
return render(request, "app1/my_form.html", context={ 'form': pd })
def post(self, request):
pd = PersonForm(request.POST)
if pd.is_valid():
name = pd.cleaned_data['name']
age = pd.cleaned_data['age']
height = pd.cleaned_data['height']
p = Person()
p.name = name
p.age = age
p.height = height
try:
p.save()
except IntegrityError as e:
e = 'this data already exists in the database'
return render(request, "app1/my_form.html", context={ 'form': pd, 'e': e})
context = {
'person': {
'name': name,
'age': age,
'height': height,
},
'form': pd
}
else:
print("Form is invalid")
context = { 'form': pd }
return render(request, "app1/my_form.html", context=context)
in the template ,i can access the erroe as {{ e }}

- 91
- 3
For class-based views you can catch the error, add it to the error list and use FormMixin.form_invalid
to re-render the form template, just as if standard validation failed:
class YourView(CreateView):
...
def form_valid(self, form):
try:
return super().form_valid(form)
except IntegrityError as e:
form.add_error(None, e)
return self.form_invalid(form)

- 11
- 1
- 2
This is how I did it - simple ternary use.simple IntegrityError use

- 1
- 1
-
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/33092659) – Imperial_J Nov 08 '22 at 03:16
Just import IntegrityError
from django.db import IntegrityError
and use it inside try/Except
try:
//Do what is needed to be done
except IntegrityError as e:
//return what is supposed to be returned
Thanks @Soren I just Edited my answer

- 2,943
- 23
- 19