Django 1.6 - “当autocommit关闭时,最外面的'atomic'块不能使用savepoint = False。”

时间:2015-04-13 23:49:58

标签: django transactions

在django 1.5天内,如果我想手动管理交易(或交易中的交易),我会做这样的事情:

@transaction.commit_manually
def my_method():
    master_sid = transaction.savepoint()
    for item in things_to_process:
        inner_sid = transaction.savepoint()
        # Make changes, save models, etc.
        ...
        if I_want_to_keep_this_iterations_changes:
            transaction.savepoint_commit(inner_sid)
        else:
            transaction.savepoint_rollback(inner_sid)
    if I_want_to_keep_all_un_rolled_back_changes_from_loop:
        transaction.savepoint_commit(master_sid)
    else:
        transaction.savepoint_rollback(master_sid)

如果我正确理解the Django docs,升级到Django 1.6+时,我应该将上面的内容更改为:

def my_method():
    transaction.set_autocommit(False)
    try:
        # Same code as above
    finally:
        transaction.set_autocommit(True)

但是,在Django 1.6+中,如果在autocommit为False时调用model.save(),Django将引发以下错误:

  

TransactionManagementError:最外层的'原子'块无法使用   自动提交关闭时,savepoint = False。

那么,如何在autocommit为false时保存模型? 我的旧Django 1.5代码的现代替代品是什么?

2 个答案:

答案 0 :(得分:4)

您应该使用 transaction.atomic()

def my_method():
    with transaction.atomic():
        for item in things_to_process:
            with transaction.atomic():
                # Make changes, save models, etc.
                ...
                if I_want_to_roll_back_this_iterations_changes:
                    raise Exception('inner rollback')
        if I_want_to_roll_back_changes_from_loop:
            raise Exception('mater rollback')

transaction.atomic()将处理提交和回滚,它可以嵌套。

Relevant docs

答案 1 :(得分:-1)

您应该阅读controlling transactions explicitly

特别

  

如果您在回滚发生之前尝试运行数据库查询,Django将引发TransactionManagementError。当与ORM相关的信号处理程序引发异常时,您可能还会遇到此行为。

  

关闭自动提交时,您可以使用原子。它只会使用保存点,即使对于最外面的块,如果使用savepoint = False声明最外面的块,它也会引发异常。