Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Django事务:如何在回滚期间运行额外代码?_Django_Transactions - Fatal编程技术网

Django事务:如何在回滚期间运行额外代码?

Django事务:如何在回滚期间运行额外代码?,django,transactions,Django,Transactions,假设您的web应用程序中有一个用户模型,并且您需要通过API使该用户与外部服务保持同步。因此,当您在本地创建用户时,也需要远程创建它 您的所有操作都在transaction.atomic()下,并且您尝试将所有第三方API调用保留在原子块之后,这是合理的 但是,一个系统作为一个系统,它会变得越来越复杂,直到您在更新调用中有一些很难删除的第三方调用为止 也就是说,有没有办法扩展Django的事务机制,比如添加一些回调函数,比如rollback.add\u callback(clean\u第三方用户

假设您的web应用程序中有一个
用户
模型,并且您需要通过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将其延迟到事务成功后再执行。撤销一开始从未做过的事情要容易得多

但听起来你也已经同意了。

看看这个