如何在 Django 中捕获 A 'UNIQUE constraint failed' 404

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

我如何在下面的代码中专门捕获一个 UNIQUE 约束失败 404,我知道我必须在(此处?)部分添加一些内容

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

except IntegrityError:

这就是您所需要的。

已编辑 @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 的可能性很大。

通常 "ask for forgiveness" 原则是编程中的一个好习惯,但在这种特殊情况下,我不推荐它。

您要查找的异常是 IntegrityError。您可以通过简单地删除 try-catch 块并强制执行该异常来轻松地自己解决这个问题。回溯显示异常 class.

问题是,有几种不同类型的完整性错误,因此在您的 try-catch 块中,您必须检查 if ex.pgcode == 23505 之类的内容,以查看这是否实际上是 UNIQUE 约束错误。之前已经在这里回答过:IntegrityError: distinguish between unique constraint and not null violations

情况变得更糟:每个 ORM 都有不同的错误代码,字段名称不会是 pgcode,而是其他名称,并且一些 ORM 根本不会抛出 UNIQUE 约束。所以如果你正在构建一个可重用的应用程序或者如果你正在使用一个很糟糕的 ORM(例如 MySQL)或者如果你不确定你是否会在将来的某个时间更改你的项目的数据库,你应该不要这样做!

更好的方法是简单地删除 try-catch 块并在保存之前检查对象是否已经在数据库中。

我不知道在你的情况下哪个字段是唯一的,所以我假设它是 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)

恕我直言,我建议通过 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

Unique constraint fail return :"('UNIQUE constraint failed: 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

对于Python > 3.5

你需要:

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

示例:

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 

发现于 django.db.models.query.QuerySet._create_object_from_params。并进行一些更改:

from typing import Any, Dict, Type  
from django.db import transaction, IntegrityError, Model


def get_or_create_obj(model: Type[Model], defaults: Dict[str, Any] = None, **kwargs: Any):
    defaults = defaults or {}
    try:
        with transaction.atomic():
            return model.objects.create(**kwargs, **defaults), True
    except IntegrityError as e:
        try:
            return model.objects.using("default").get(**kwargs), False
        except model.DoesNotExist:
            pass
        raise e