Django的文档说明了transaction.atomic()
和例外:
https://docs.djangoproject.com/en/1.10/topics/db/transactions/#django.db.transaction.atomic
避免在原子内捕获异常!
当退出原子块时,Django会查看它是正常退出还是有异常来确定是提交还是回滚。如果你捕获并处理原子块中的异常,你可以向Django隐瞒问题已经发生的事实。这可能会导致意外行为。
这主要是DatabaseError及其子类(例如IntegrityError)的问题。发生这样的错误后,事务被破坏,Django将在原子块结束时执行回滚。如果您在回滚发生之前尝试运行数据库查询,Django将引发TransactionManagementError。当与ORM相关的信号处理程序引发异常时,您可能还会遇到此行为。
捕获数据库错误的正确方法是围绕原子块,如上所示。如有必要,为此目的添加额外的原子块。此模式具有另一个优点:它可以明确地分隔在发生异常时将回滚哪些操作。
如果捕获原始SQL查询引发的异常,则Django的行为未指定且与数据库有关。
这样做是否可行,或者这是否导致"意外行为"?
with transaction.atomic():
# something
try:
# something
except:
logger.exception("Report error here.")
raise
答案 0 :(得分:1)
基于文档,我会确保重新引发正确的异常,以及您可能独立处理的其他错误。对于django,只需要在与数据库通信时获得有关出错的通知。
with transaction.atomic():
# something
try:
# something
except DatabaseError as db_err:
logger.exception("Report error here.")
raise db_err
except Exception:
# do something else
# no need to reraise
# as long as you handle it properly and db integrity is guaranteed
答案 1 :(得分:0)
这样做是否可行,或者这是否导致"意外行为"?
with transaction.atomic():
# something
try:
# something
except:
logger.exception("Report error here.")
raise
除了bare except子句(你至少想要except Exception:
),这是好的,假设你的记录器没有触及数据库(这无论如何都是一个非常糟糕的主意)和记录器调用不会引发另一个异常(在这种情况下,我不知道实际会发生什么)。
但是你得到了相同的结果,反转transaction.atomic()
块和try/except
,即:
try:
with transaction.atomic():
# something
# something
except Exception:
logger.exception("Report error here.")
raise