在Django中使用原子块进行错误处理

bee*_*ego 1 database django transactions rollback

我有一个Django 1.9应用程序,该应用程序正在运行一段代码,根据对某些远程API的查询结果,对数据库进行更改。例如,这可能是有关提交,文件更改,审阅者,拉取请求等的数据,这些数据我想另存为数据库中的实体。

commit_data = commit_API_client.get_commit_info(argument1, argument2)
new_commit = models.Commit.Create(**commit_data)

#if the last API failed, this will fail
#I will need to run this again to get these files, so I need
#to get the commit all over again, too
files = file_API_client.get_file_info(new_commit.id)
new_files = models.Files.Create(**files)

#do some more stuff here 
Run Code Online (Sandbox Code Playgroud)

我正在调用的少数几个API之一很有可能会返回一些错误而不是有效数据。实际上,我基本上需要使这一部分成为一个原子事务,以便如果从中没有返回错误HTTP requests,我会将所有更改提交给数据库。否则,如果2个API正确返回,我可能会丢失一些数据,但第3个不会。

我看到Django支持commit hooks数据库事务,但是我想知道这是否适用于这种情况,以及我将如何实现这一点。

Kev*_*nry 5

如果要使其成为原子操作,只需将其包装在中即可transaction.atomic()。如果您的任何代码引发异常,则整个块将回滚。如果您仅从远程API读取数据,则应该可以正常工作。典型的模式是:

def my_function():
    try:
        with transaction.atomic():
            # Do your work here
            pass
    except Exception:
        # Do some error handling
        pass
Run Code Online (Sandbox Code Playgroud)

Django确实有一个on_commit钩子,但这在这里并不适用。其目的是在事务成功完成后运行一些代码。例如,如果交易成功,您可以使用它将一些日志数据写入远程API。