事务管理块以挂起的COMMIT/ROLLBACK结束

Joe*_*Joe 31 django transactions

我有一个视图功能:

@transaction.commit_manually
def xyz(request):
    if ABC:
        success = something()

        if success:
            status = "success"
            transaction.commit()

        else:
            status = "dataerrors"
            transaction.rollback()
    else:
        status = "uploadproblem"
        transaction.rollback()

    return render(request, "template.html", {
        'status': status,
    })
Run Code Online (Sandbox Code Playgroud)

我相信每个代码路径都以这种或那种方式结束事务.但Django似乎在抱怨它没有.有任何想法吗?

Django Version:     1.3
Exception Type:     TransactionManagementError
Exception Value:    Transaction managed block ended with pending COMMIT/ROLLBACK
Run Code Online (Sandbox Code Playgroud)

编辑:没有其他异常被抛出来改变代码路径.

Ger*_*eyn 86

在得到类似问题并浪费时间后,我想出了如何调试这种情况.

出于某种原因,@ transaction.commit_manually装饰器会使函数中出现的异常静音.

暂时从您的函数中删除装饰器,您现在将看到异常,修复它并将装饰器放回去!


Cer*_*rin 9

我有同样的问题.我发现的唯一解决方案是使用try/finally子句来确保在渲染之后发生提交.

@transaction.commit_manually
def xyz(request):
    committed = False
    try:
        if ABC:
            success = something()

            if success:
                status = "success"
                transaction.commit()
                committed = True

            else:
                status = "dataerrors"
                transaction.rollback()
                committed = True
        else:
            status = "uploadproblem"
            transaction.rollback()
            committed = True

        return render(request, "template.html", {
            'status': status,
        })
    finally:
        if not committed:
            transaction.rollback() # or .commit() depending on your error-handling logic
Run Code Online (Sandbox Code Playgroud)

没有任何意义,但它对我有用.

  • 这是一个很好的解决方案,但不是使用变量`commited`,而是使用`transaction.is_dirty()`.如果可以,请检查django事务中间件,它们完全相同. (3认同)