Rajat Saxena
Rajat Saxena

Reputation: 3925

Django: Catching Integrity Error and showing a customized message using template

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?

Upvotes: 97

Views: 104912

Answers (8)

raven88
raven88

Reputation: 1

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

Upvotes: 0

totoro84
totoro84

Reputation: 11

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)

Upvotes: 1

Chirael
Chirael

Reputation: 3085

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.

Upvotes: 17

Ahmed Adewale
Ahmed Adewale

Reputation: 3133

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

Upvotes: -3

Luke Marak
Luke Marak

Reputation: 101

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 }}

Upvotes: 2

Krzysiek Hans
Krzysiek Hans

Reputation: 41

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

Upvotes: 4

bruno desthuilliers
bruno desthuilliers

Reputation: 77912

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.

Upvotes: 3

Joe
Joe

Reputation: 47649

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.

Upvotes: 200

Related Questions