Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/21.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中成功使用嵌套@transaction.commit__Django_Transactions - Fatal编程技术网

在Django中成功使用嵌套@transaction.commit_

在Django中成功使用嵌套@transaction.commit_,django,transactions,Django,Transactions,考虑这个简单的例子: # a bank account class class Account: @transaction.commit_on_success def withdraw(self, amount): # code to withdraw money from the account @transaction.commit_on_success def add(self, amount): # code to ad

考虑这个简单的例子:

# a bank account class
class Account:
    @transaction.commit_on_success
    def withdraw(self, amount):
        # code to withdraw money from the account 

    @transaction.commit_on_success
    def add(self, amount):
        # code to add money to the account

# somewhere else
@transaction.commit_on_success
def makeMoneyTransaction(src_account, dst_account, amount):
    src_account.withdraw(amount)
    dst_account.add(amount)
(摘自)

如果在
Account.add()
中出现异常,则
Account.draw()
中的交易仍将提交,资金将丢失,因为Django当前不处理嵌套交易

如果不对Django应用修补程序,我们如何确保提交被发送到数据库,但仅当
@transaction.commit\u on\u success
decorator下的主函数完成而不引发异常时

我偶然发现了这个片段:它似乎可以完成这项工作。如果我使用它,有什么缺点需要注意吗

如果你能帮忙的话,请提前表示衷心的感谢

另外,为了便于查看,我复制了前面引用的代码片段:

def nested_commit_on_success(func):
    """Like commit_on_success, but doesn't commit existing transactions.

    This decorator is used to run a function within the scope of a 
    database transaction, committing the transaction on success and
    rolling it back if an exception occurs.

    Unlike the standard transaction.commit_on_success decorator, this
    version first checks whether a transaction is already active.  If so
    then it doesn't perform any commits or rollbacks, leaving that up to
    whoever is managing the active transaction.
    """
    commit_on_success = transaction.commit_on_success(func)
    def _nested_commit_on_success(*args, **kwds):
        if transaction.is_managed():
            return func(*args,**kwds)
        else:
            return commit_on_success(*args,**kwds)
    return transaction.wraps(func)(_nested_commit_on_success)

这个代码段的问题在于,它不能在不回滚外部事务的情况下回滚内部事务。例如:

@nested_commit_on_success
def inner():
    # [do stuff in the DB]

@nested_commit_on_success
def outer():
    # [do stuff in the DB]
    try:
        inner()
    except:
        # this did not work, but we want to handle the error and
        # do something else instead:

        # [do stuff in the DB]

outer()
在上面的示例中,即使
internal()
引发异常,其内容也不会回滚

你需要的是一个内部“事务”的框架。对于您的代码,它可能如下所示:

# a bank account class
class Account:
    def withdraw(self, amount):
        sid = transaction.savepoint()
        try:
            # code to withdraw money from the account
        except:
            transaction.savepoint_rollback(sid)
            raise

    def add(self, amount):
        sid = transaction.savepoint()
        try:
            # code to add money to the account
        except:
            transaction.savepoint_rollback(sid)
            raise

# somewhere else
@transaction.commit_on_success
def makeMoneyTransaction(src_account, dst_account, amount):
    src_account.withdraw(amount)
    dst_account.add(amount)
从Django 1.6开始,decorator就完全做到了这一点:它使用一个事务作为decorator的外部使用,而任何内部使用都使用一个保存点。

Django 1.6介绍了这一点,这正是我想要的


它不仅支持“嵌套”事务,而且还取代了旧的、功能较弱的装饰程序。在不同的Django应用程序之间有一个独特且一致的事务管理行为是很好的。

我甚至不确定这个代码片段是否能正常工作。现在它似乎已经4岁了,有人说它在这里不起作用:谢谢,你的解决方案看起来确实更安全。我希望Django将在未来的版本中引入使用保存点的@atomic decorator。同时,我会继续使用我的,因为它使用起来更简单。如果不忽略从子方法引发的异常,它仍然会工作。