how do catch A 'UNIQUE constraint failed' 404 in django

For Python > 3.5

You need:

except IntegrityError as e: 
                if 'unique constraint' in e.args:

Example:

from django.db import IntegrityError

 for column in csv.reader(io_string, delimiter=',', quotechar="|"):
     try:
         _, created = Brand.objects.update_or_create(
            system_id=column[0],
            name=column[1],
            slug=column[2],
            description=column[3],
            image=column[4]
           )
     except IntegrityError as e: 
           if 'unique constraint' in e.args:
               continue 

from django.db import IntegrityError

except IntegrityError:

This is what you need.

EDITED for @mbrochh:

from django.db import IntegrityError

except IntegrityError as e: 
    if 'unique constraint' in e.message: # or e.args[0] from Django 1.10
        #do something

Yes, you can be more precise but in question case UNIQUE failed is highly likely.


IMHO, I would recommend to resolve this situation by get_or_create().

new_obj, created = AnswerModel.objects.get_or_create(user=user, yes_question=question_model)
if created:
    do_something_for_new_object(new_obj)
else:
    logging.error("Duplicated item.")
    return

Usually the "ask for forgiveness" principle is a good practice in programming but in this special case, I would not recommend it.

The exception you are looking for is IntegrityError. You could have easily figured that out yourself by simply removing the try-catch block and forcing that exception. The traceback shows the exception class.

The problem is, there are several different kinds of integrity errors, so inside your try-catch block you would have to check for something like if ex.pgcode == 23505 to see if this is actually a UNIQUE constraint error. This has been answered before here: IntegrityError: distinguish between unique constraint and not null violations

It gets worse: Each ORM has different error codes, the field name will not be pgcode but something else and some ORMs don't throw UNIQUE constraints at all. So if you are building a reusable app or if you are using a ORM that sucks (such as MySQL) or if you are not sure if you will change the database of your project at some time in the future, you should not do this!

The better way is simply removing the try-catch block and check if the object is already in the database before saving.

I don't know which field is UNIQUE in your case, so I will just assume that it is the user field. Your code would look something like this:

answers = AnswerModel.objects.filter(user=user)
if answers:
   return HttpResponseRedirect('/user/already_exists')
obj = AnswerModel.objects.create(user=user, yes_question=question_model)
...

If you are dealing with a combined unique constraint, the first line would be this:

answers = AnswerModel.objects.filter(user=user, yes_question=question_model)

Tags:

Python

Django