在Django事务中重复保存导致InternalError而不是IntegrityError

时间:2013-01-26 07:30:42

标签: django transactions django-views django-orm

我使用PostgreSQL作为psycopg2的后端,我注意到一些对我来说很奇怪的东西。我的设置如下:

class ParentModel(models.Model):
    field1 = models.IntegerField()

class ChildModel(ParentModel):
    field2 = models.IntegerField(unique=True)

当我尝试从shell中保存带有重复field2的ChildModel对象时,我得到的是InternalError而不是IntegrityError,但是如果在transaction.commit_on_success块中完成保存,那么

with transaction.commit_on_success():
    newObj = ChildModel(field1=5, field2=10) # Assume that a ChildModel with field2 == 10 exists 

在事务块之外,我得到了一个IntegrityError,正如我所料。

在视图代码中运行时,即使使用保存点,我也总是在更新失败后获得InternalError:

try:
    sid = transaction.savepoint()
    newObj = ChildModel(field1=5, field2=10) # Assume that a ChildModel with field2 == 10 exists
    transaction.savepoint_commit(sid)
except IntegrityError:
    transaction.savepoint_rollback(sid)
except InternalError:
    transaction.savepoint_rollback(sid)

... other stuff ... # raises InternalError on next database hit

如果我在带有block的commit_on_success事务中执行此操作,而不是使用保存点,则会发生同样的事情。我安装了TransactionMiddleware,我没有在自动提交模式下运行PostgreSQL。

我可以通过简单地检查确保重复对象不存在来避免这种情况,但我想知道我对Django事务的理解出了什么问题。是什么给了什么?

1 个答案:

答案 0 :(得分:3)

我遇到了完全相同的问题。我查看了postgres日志文件,可以看到在查询之后运行另一个查询导致完整性错误,导致实际错误在默认事务设置中黯然失色。这都是django-debug-toolbar的错误。

谷歌向我指出https://github.com/django-debug-toolbar/django-debug-toolbar/issues/351这似乎解决了这个问题。

简而言之,如果您使用的是django-debug-toolbar< = 0.9.4,则禁用它可以解决问题。