Управляемый блок транзакции Django завершился с ожиданием COMMIT / ROLLBACK - PullRequest
4 голосов
/ 31 марта 2012

У меня есть функция просмотра, которой нужно управлять транзакциями вручную, но когда я применяю декоратор @transaction.commit_manually, django ВСЕГДА вызывает следующее исключение.

Как видно из трассировки кода ниже,транзакция фиксируется непосредственно перед возвратом из представления.

Я использую sqlite, как на windows, так и на linux, с 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 ]

17 голосов
/ 31 марта 2012

Оказывается, что во время рендеринга шаблона был доступ к базе данных, поэтому причиной был обычный шаблон, такой как:

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 показывают, что декораторы управления транзакциями скрывают все исключения и вместо этого вызывают исключение управления транзакциями.К сожалению, самый простой способ диагностировать это - запустить без декоратора и посмотреть, не возникло ли исключение, или обернуть весь вид в попытку / исключение.

1 голос
/ 31 марта 2012

Ссылки Документ

Если ваше представление изменяет данные и не выполняет коммит () или откат (), Django вызовет исключение TransactionManagementError.

Итак, у вас есть изменения в транзакции, и вам нужен откат или фиксация до последнего возврата.transaction.rollback_unless_managed() не будет работать, потому что транзакция внутри commit_manually является управляемой .

0 голосов
/ 25 апреля 2012

У меня была эта проблема, и я решил ее, украсив процессор контекста 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):
    ...

Даже чтения из БД требуют фиксации / отката (в том числе внутри контекстного процессора) https://docs.djangoproject.com/en/dev/topics/db/transactions/#requirements-for-transaction-handling

...