Django Transaction托管块以挂起的COMMIT / ROLLBACK结束

时间:2012-03-31 11:03:58

标签: python django sqlite django-orm

我有一个需要手动管理事务的视图功能,但是当我应用@transaction.commit_manually装饰器时,django总是会引发以下异常。

从下面的代码跟踪中可以看到,事务是在从视图返回之前提交的。

我在Windows和Linux上使用sqlite,使用django 1.4。

以下是django_trace的输出,后跟异常。要清楚:无论我是否使用django_trace,都会发生这种情况,并且当没有装饰器时,不会引发任何异常。这不是由“吞噬”的例外造成的。

请注意,下面的第60行位于上下文处理器内部,因此位于commit_manually包装视图之外。

01->mainapp.views:1321:         transaction.commit()
01->mainapp.views:1322:         return render_to_response('mainapp/templates/incorporate.html',
01->mainapp.views:1323:                                       RequestContext(request, form_params))
02-->mainapp.views:60:     transaction.rollback_unless_managed()
02-->mainapp.views:61:     return {'home_login_form': AuthenticationForm(request)}
Traceback (most recent call last):
  File "C:\Users\Marcin\Documents\oneclickcos\lib\site-packages\django\contrib\staticfiles\handlers.py", line 67, in __call__
    return self.application(environ, start_response)
  File "C:\Users\Marcin\Documents\oneclickcos\lib\site-packages\django\contrib\staticfiles\handlers.py", line 67, in __call__
    return self.application(environ, start_response)
  File "C:\Users\Marcin\Documents\oneclickcos\lib\site-packages\django\core\handlers\wsgi.py", line 241, in __call__
    response = self.get_response(request)
  File "C:\Users\Marcin\Documents\oneclickcos\lib\site-packages\django\core\handlers\base.py", line 179, in get_response
    response = self.handle_uncaught_exception(request, resolver, sys.exc_info())
  File "C:\Users\Marcin\Documents\oneclickcos\lib\site-packages\django\core\handlers\base.py", line 221, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "C:\Users\Marcin\Documents\oneclickcos\lib\site-packages\django\core\handlers\base.py", line 111, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File "C:\Users\Marcin\Documents\oneclickcos\oneclickcos\mainapp\decorators.py", line 26, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "C:\Users\Marcin\Documents\oneclickcos\lib\site-packages\django\db\transaction.py", line 209, in inner
    return func(*args, **kwargs)
  File "C:\Users\Marcin\Documents\oneclickcos\lib\site-packages\django\db\transaction.py", line 203, in __exit__
    self.exiting(exc_value, self.using)
  File "C:\Users\Marcin\Documents\oneclickcos\lib\site-packages\django\db\transaction.py", line 288, in exiting
    leave_transaction_management(using=using)
  File "C:\Users\Marcin\Documents\oneclickcos\lib\site-packages\django\db\transaction.py", line 52, in leave_transaction_management
    connection.leave_transaction_management()
  File "C:\Users\Marcin\Documents\oneclickcos\lib\site-packages\django\db\backends\__init__.py", line 119, in leave_transaction_management
    raise TransactionManagementError("Transaction managed block ended with "
TransactionManagementError: Transaction managed block ended with pending COMMIT/ROLLBACK

要说清楚,我已经检查了关于这个主题的其他问题,他们没有解决我的问题。

3 个答案:

答案 0 :(得分:17)

事实证明,在模板渲染过程中,存在数据库访问,因此通常的模式如下:

return render_to_response('mainapp/templates/incorporate.html',
                          RequestContext(request, form_params))

是问题的原因。我需要将其替换为:

retval = render_to_response('mainapp/templates/incorporate.html',
                                      RequestContext(request, form_params))
transaction.commit()
return retval

此外,其他SO答案显示事务管理装饰器隐藏所有异常,而是引发事务管理异常。不幸的是,最简单的诊断方法是在没有装饰器的情况下运行,看看是否发生异常,或者将整个视图包装在try / except中。

答案 1 :(得分:1)

参考the doc

  

如果您的视图更改数据并且没有commit()或rollback(),Django将引发TransactionManagementError异常。

因此,您在事务中进行了更改,并且需要在最后一次返回之前进行回滚或提交。 transaction.rollback_unless_managed()无效,因为commit_manually内的交易已管理

答案 2 :(得分:0)

我遇到了这个问题并通过用transaction.commit_on_success装饰上下文处理器来解决它,例如

@transaction.commit_manually
def my_view(request):
    ...
    transaction.commit()
    return render_to_response("template.html", context_instance=RequestContext(request, my_ctx))


@transaction.commit_on_success
def my_context_processor(request):
    ...

甚至db读取都需要提交/回滚(包括上下文处理器内的那些)https://docs.djangoproject.com/en/dev/topics/db/transactions/#requirements-for-transaction-handling