Django、Postgresql与完整性错误
我之前用的是mysql数据库,如果我想插入一条记录,可以用一个叫INSERT IGNORE的命令,这样我就可以直接把数据放进去,如果出现冲突就直接忽略掉。
现在我在做一个Django项目,使用的是postgresql数据库,并且在一个循环里进行多次保存。不过,我觉得如果出现了IntegrityError(我在代码中是忽略这个错误的),那么我可能会丢失很多我想插入的对象……我该怎么解决这个问题呢:
for thing in things:
try:
#potentially dangerous save..
obj = Thing(stuff=10)
obj.save()
except IntegrityError:
pass
假设在循环的第5次时出现了IntegrityError,那么哪些对象会被插入到数据库里呢?
2 个回答
1
通过不忽略错误?
你写的代码大概是这样的。
You: Save all the things.
Django: You're about to violate data integrity in your database.
You: I don't care.
Django: I can't simply corrupt your data. I'll just throw away
the things that would corrupt your data.
You: That's what I wanted.
虽然这种做法在某些应用中可能合适,但对大多数情况来说并不合适。
你需要决定当数据不符合你的完整性约束时,应该怎么处理这些数据。同时,你还需要修复那些让不良数据进入save()方法的代码。关于这个问题,查看一下表单和字段验证的文档可能会有帮助。
8
这要看你是怎么管理你的事务的。
在Postgres数据库中,如果事务中的某个查询出错,后面的所有查询也会失败,并显示错误信息“当前事务已中止,查询在事务块结束前会被忽略”。
为了处理这个问题,你应该在异常处理块中使用transaction.savepoint_rollback。
具体可以参考Django的文档,里面有关于如何在PostgreSQL事务中处理异常的说明,链接在这里:处理PostgreSQL事务中的异常
文档中有一个示例:
a.save() # Succeeds, and never undone by savepoint rollback
try:
sid = transaction.savepoint()
b.save() # Could throw exception
transaction.savepoint_commit(sid)
except IntegrityError:
transaction.savepoint_rollback(sid)
c.save() # Succeeds, and a.save() is never undone