Django事务:如何在回滚期间运行额外代码?
假设您的web应用程序中有一个Django事务:如何在回滚期间运行额外代码?,django,transactions,Django,Transactions,假设您的web应用程序中有一个用户模型,并且您需要通过API使该用户与外部服务保持同步。因此,当您在本地创建用户时,也需要远程创建它 您的所有操作都在transaction.atomic()下,并且您尝试将所有第三方API调用保留在原子块之后,这是合理的 但是,一个系统作为一个系统,它会变得越来越复杂,直到您在更新调用中有一些很难删除的第三方调用为止 也就是说,有没有办法扩展Django的事务机制,比如添加一些回调函数,比如rollback.add\u callback(clean\u第三方用户
用户
模型,并且您需要通过API使该用户与外部服务保持同步。因此,当您在本地创建用户时,也需要远程创建它
您的所有操作都在transaction.atomic()
下,并且您尝试将所有第三方API调用保留在原子块之后,这是合理的
但是,一个系统作为一个系统,它会变得越来越复杂,直到您在更新调用中有一些很难删除的第三方调用为止
也就是说,有没有办法扩展Django的事务机制,比如添加一些回调函数,比如rollback.add\u callback(clean\u第三方用户(user\u id=134))
这样,我可以保证所有必要的回滚操作都已执行,并且我的系统处于同步状态?Django的事务挂钩代码的作者解释了为什么在提交()上有
,而在回滚()上没有,
:
回滚钩子比提交钩子更难健壮地实现,因为各种事情都可能导致隐式回滚。例如,您的数据库连接被删除,因为您的进程在没有正常关闭的情况下被终止:您的回滚挂钩将永远不会运行
由于回滚通常由异常触发,因此一种简单的方法是捕获任何异常并在那里运行撤消代码
try:
with transaction.atomic():
# Do database stuff
# Do external stuff
except:
# We know the database stuff has rolled back, so...
# Undo external stuff
raise
这不是特别优雅。我同意来自同一来源的以下观点:
解决方案很简单:不要在原子块(事务)期间执行某些操作,然后在事务失败时撤消它,而是使用on_commit将其延迟到事务成功后再执行。撤销一开始从未做过的事情要容易得多
但听起来你也已经同意了。看看这个