Django 1.6 TransactionManagementError: la base de datos no se comporta correctamente cuando la confirmación automática está desactivada
django-1.6 (5)
Estoy intentando actualizar un proyecto de Django 1.5.5 a Django 1.6, sin embargo, he estado recibiendo este error en todas partes.
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''.
He eliminado TransactionMiddleware
de MIDDLEWARE_CLASSES
y lo MIDDLEWARE_CLASSES
reemplazado con ATOMIC_REQUESTS = True
. (Mismo error incluso si no hago este paso)
¿Alguien puede arrojar algo de luz sobre esto?
Creo que el error se debe a las limitaciones de Sqlite3. Para resolver esto, tuve que cambiar de Sqlite3 a un motor de base de datos más robusto como postgrsql_psycopg2
.
El código que lanza el error ( transaction.py:244
) proporciona una pista en el comentario:
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''.")
Mirar la última Documentación del Sur (0.8.4) arroja más luz sobre los problemas con Sqlite3: http://south.readthedocs.org/en/latest/databaseapi.html#database-specific-issues
SQLite no admite de forma nativa la modificación de muchos esquemas, pero South tiene soluciones para permitir la eliminación / alteración de columnas. Sin embargo, los índices únicos aún no son compatibles; El sur ignorará silenciosamente cualquiera de tales órdenes.
En mi caso, tengo índices únicos en mis modelos que parecen no ser compatibles.
Me encontré con el mismo problema al usar sqlite3. Descubrí que estaba usando transaction.commit_on_success
. Al cambiar eso a transaction.atomic()
, el problema se resolvió.
Me encontré con esto con db sqlite3, utilizando Django 1.6. Aquí están las soluciones.
django.middleware.transaction.TransactionMiddleware ha quedado en desuso. Si no tiene esto en su archivo settings.py, no debería recibir el error.
Accidentalmente, encontré que incluir ATOMIC_REQUESTS: True funciona para solucionar el error si dejaste django.middleware.transaction.TransactionMiddleware en tu lista de middlewares.
P.ej
DATABASES = {
''default'': {
''ENGINE'': ''django.db.backends.sqlite3'',
''NAME'': ''sqlite3-db'',
''ATOMIC_REQUESTS'': True
}
}
Tuve el mismo problema en mi migración forwards
(curiosamente, no ocurrió en mi migración backwards
), y no tengo TransactionMiddleware
en mi configuración. Mi solución fue evitar el uso del método get_or_create
y hacer lo mismo más verbalmente. De los documentos de Django :
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()
A continuación, puede crear su propio método pseudo- get_or_create
esta manera:
def fake_get_or_create(model, *args, **kwargs):
try:
obj = model.objects.get(**kwargs)
except model.DoesNotExist:
obj = model(**kwargs)
obj.save()
return obj
Que puedes usar haciendo lo siguiente
obj = fake_get_or_create(Person, first_name=''John'', last_name=''Lennon'')
agrega estos a tus migraciones
def forwards(self, orm):
if connection.vendor == ''sqlite'':
set_autocommit(True)
y establecerá el compromiso automático en verdadero para las migraciones :)