Django 1.6 TransactionManagementError:当autocommit关闭时,数据库的行为不正常

时间:2013-11-18 02:46:19

标签: django django-1.6

我正在尝试将项目从Django 1.5.5更新为Django 1.6但是我到处都遇到了这个错误。

Traceback (most recent call last):

File "project/virtualenv/lib/python2.7/site-packages/django/core/handlers/base.py", line 114, in get_response
  response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "project/virtualenv/lib/python2.7/site-packages/django/contrib/admin/sites.py", line 215, in wrapper
  return self.admin_view(view, cacheable)(*args, **kwargs)

File "project/virtualenv/lib/python2.7/site-packages/django/utils/decorators.py", line 99, in _wrapped_view
  response = view_func(request, *args, **kwargs)

File "project/virtualenv/lib/python2.7/site-packages/django/views/decorators/cache.py", line 52, in _wrapped_view_func
  response = view_func(request, *args, **kwargs)

File "project/virtualenv/lib/python2.7/site-packages/django/contrib/admin/sites.py", line 197, in inner
  return self.login(request)

File "project/virtualenv/lib/python2.7/site-packages/django/views/decorators/cache.py", line 52, in _wrapped_view_func
  response = view_func(request, *args, **kwargs)

File "project/virtualenv/lib/python2.7/site-packages/django/contrib/admin/sites.py", line 330, in login
  return login(request, **defaults)

File "project/virtualenv/lib/python2.7/site-packages/django/views/decorators/debug.py", line 75, in sensitive_post_parameters_wrapper
  return view(request, *args, **kwargs)

File "project/virtualenv/lib/python2.7/site-packages/django/utils/decorators.py", line 99, in _wrapped_view
  response = view_func(request, *args, **kwargs)

File "project/virtualenv/lib/python2.7/site-packages/django/views/decorators/cache.py", line 52, in _wrapped_view_func
  response = view_func(request, *args, **kwargs)

File "project/virtualenv/lib/python2.7/site-packages/django/contrib/auth/views.py", line 43, in login
  auth_login(request, form.get_user())

File "project/virtualenv/lib/python2.7/site-packages/django/contrib/auth/__init__.py", line 83, in login
  request.session.cycle_key()

File "project/virtualenv/lib/python2.7/site-packages/django/contrib/sessions/backends/base.py", line 277, in cycle_key
  self.create()

File "project/virtualenv/lib/python2.7/site-packages/django/contrib/sessions/backends/db.py", line 40, in create
  self.save(must_create=True)

File "project/virtualenv/lib/python2.7/site-packages/django/contrib/sessions/backends/db.py", line 62, in save
  with transaction.atomic(using=using):

File "project/virtualenv/lib/python2.7/site-packages/django/db/transaction.py", line 244, in __enter__
  "Your database backend doesn't behave properly when "

TransactionManagementError: Your database backend doesn't behave properly when autocommit is off. Turn it on before using 'atomic'.

我已从TransactionMiddleware移除了MIDDLEWARE_CLASSES,并将其替换为ATOMIC_REQUESTS = True。 (即使我不执行此步骤也会出现相同的错误)

有人可以对此有所了解吗?

5 个答案:

答案 0 :(得分:22)

我使用Django 1.6在sqlite3 db中遇到了这个问题。以下是解决方案。

  1. django.middleware.transaction.TransactionMiddleware已被弃用。如果你的settings.py文件中没有这个,你不应该收到错误。

  2. 无意中,我发现如果您在中间件列表中留下了django.middleware.transaction.TransactionMiddleware,那么包括ATOMIC_REQUESTS:True会解决错误。

  3. E.g。

    DATABASES = {
      'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'sqlite3-db',
        'ATOMIC_REQUESTS': True
      }
    }
    

答案 1 :(得分:14)

我在forwards迁移中遇到了同样的问题(有趣的是,我的backwards迁移中没有发生过这种情况),并且我的设置中没有TransactionMiddleware。我的解决方法是避免使用get_or_create方法,而是更冗长地执行相同的操作。来自Django docs

try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
    obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    obj.save()

然后,您可以创建自己的伪get_or_create方法,如下所示:

def fake_get_or_create(model, *args, **kwargs):
    try:
        obj = model.objects.get(**kwargs)
    except model.DoesNotExist:
        obj = model(**kwargs)
        obj.save()
    return obj

您可以通过以下方式使用

obj = fake_get_or_create(Person, first_name='John', last_name='Lennon')

答案 2 :(得分:7)

使用sqlite3时遇到了同样的问题。我发现我正在使用transaction.commit_on_success。在将其更改为transaction.atomic()时,问题已得到解决。

答案 3 :(得分:1)

我认为错误是由于Sqlite3的限制。为了解决这个问题,我不得不从Sqlite3切换到更强大的数据库引擎,如postgrsql_psycopg2

抛出错误的代码(transaction.py:244)在评论中提供了线索:

        if not connection.get_autocommit():
            # Some database adapters (namely sqlite3) don't handle
            # transactions and savepoints properly when autocommit is off.
            # Turning autocommit back on isn't an option; it would trigger
            # a premature commit. Give up if that happens.
            if connection.features.autocommits_when_autocommit_is_off:
                raise TransactionManagementError(
                    "Your database backend doesn't behave properly when "
                    "autocommit is off. Turn it on before using 'atomic'.")

查看最新的南方文档(0.8.4),可以更清楚地了解Sqlite3的问题:http://south.readthedocs.org/en/latest/databaseapi.html#database-specific-issues

  

SQLite本身并不支持很多模式更改,但是South有一些变通方法可以删除/更改列。但是,仍然不支持唯一索引;南方将默默地忽略任何此类命令。

就我而言,我的模型中有唯一的索引似乎不受支持。

答案 4 :(得分:1)

将这些添加到您的迁移

def forwards(self, orm):
    if connection.vendor == 'sqlite':
        set_autocommit(True)

并且它会将自动提交设置为true以进行迁移:)