如何捕获django中的'UNIQUE约束失败'404

Spr*_*dle 19 python django

如何在以下代码中专门捕获UNIQUE约束失败404,我知道我必须在(这里?)部分添加一些东西

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

tor*_*orm 30

from django.db import IntegrityError

except IntegrityError:
Run Code Online (Sandbox Code Playgroud)

这就是你需要的.

编辑 @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
Run Code Online (Sandbox Code Playgroud)

是的,你可以更精确,但有问题的情况UNIQUE failed很有可能.

  • 从 Django 1.10 开始,您需要使用:`if 'unique constraint' in e.args[0]` (4认同)
  • 这仍然是一个糟糕的解决方案,因为我们不知道这些消息是否会改变。检查错误代码将是更好的方法。 (3认同)
  • 这就是错误代码的全部意义!它们记录在 Postgres 官方文档中,并且永远不会改变。将某些内容与消息字符串进行比较是非常糟糕的做法。 (2认同)
  • 如果 e.args[0] 中的“唯一约束失败” (2认同)

小智 11

恕我直言,我建议通过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
Run Code Online (Sandbox Code Playgroud)

  • @nickswiss 它会起作用的。根据[文档](https://docs.djangoproject.com/en/3.2/ref/models/querysets/#get-or-create),如果参数具有唯一性约束,则“get_or_create”是原子的。 (2认同)

mbr*_*chh 7

通常“请求宽恕”原则是编程中的一个好习惯,但在这种特殊情况下,我不推荐它。

您正在寻找的例外是IntegrityError. 您可以通过简单地删除 try-catch 块并强制该异常来轻松解决这个问题。回溯显示异常类。

问题是,有几种不同类型的完整性错误,因此在您的 try-catch 块中,您必须检查类似的内容if ex.pgcode == 23505,看看这是否实际上是 UNIQUE 约束错误。这已经在这里之前回答过:IntegrityError:区分唯一约束和非空违规

更糟糕的是:每个 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)
...
Run Code Online (Sandbox Code Playgroud)

如果您正在处理组合唯一约束,则第一行将是:

answers = AnswerModel.objects.filter(user=user, yes_question=question_model)
Run Code Online (Sandbox Code Playgroud)