Как уловить A 'UNIQUE constraint failed' 404 в django

Как я могу уловить ограничение UNIQUE, не удалось выполнить 404 в следующем коде, я знаю, что мне нужно добавить что-то в разделе (здесь?)

try:
    q = AnswerModel(user=user, yes_question=question_model)
    q.save()
except ( here? ):
    return HttpResponseRedirect('/user/already_exists')

Ответ 1

from django.db import IntegrityError

except IntegrityError:

Это то, что вам нужно.

EDITED для @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

Да, вы можете быть более точным, но в вопросе случай UNIQUE failed весьма вероятен.

Ответ 2

IMHO, я бы рекомендовал разрешить эту ситуацию с помощью 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

Ответ 3

Обычно принцип "попросить прощения" является хорошей практикой в ​​программировании, но в этом специальном случае я бы не рекомендовал его.

Исключением является IntegrityError. Вы могли бы легко понять это сами, просто удалив блок try-catch и заставив это исключение. Трассировка показывает класс исключения.

Проблема в том, что существует несколько различных ошибок целостности, поэтому внутри вашего блока try-catch вам нужно будет проверить что-то вроде if ex.pgcode == 23505, чтобы убедиться, что это на самом деле ошибка UNIQUE ограничения. На этот вопрос был дан ответ: IntegrityError: различать уникальные ограничения, а не отклонения от нуля

Ухудшается: у каждого ORM разные коды ошибок, имя поля не будет pgcode, а что-то другое, а некоторые ORM вообще не бросают ограничения UNIQUE. Поэтому, если вы создаете приложение многократного использования или используете ORM, который отсасывает (например, MySQL), или если вы не уверены, измените ли вы базу данных своего проекта в будущем, вы не должны этого делать!

Лучший способ - просто удалить блок try-catch и проверить, находится ли объект в базе данных до сохранения.

Я не знаю, какое поле UNIQUE в вашем случае, поэтому я просто предполагаю, что это поле user. Ваш код будет выглядеть примерно так:

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

Если вы имеете дело с объединенным уникальным ограничением, первая строка будет следующей:

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

Ответ 4

Ошибка возврата уникального ограничения: "('Не удалось выполнить ограничение UNIQUE: notepad_notepadform.title')", что в основном является кортежем, поэтому мы можем использовать приведенный ниже код, чтобы перехватить его и сделать все необходимое:

from django.db import IntegrityError
try:
        if form.is_valid():
            form.save()

    except IntegrityError as e:
        if 'UNIQUE constraint' in str(e.args):
            #your code here