[Django]-Django 1.6 TransactionManagementError: database doesn't behave properly when autocommit is off

22πŸ‘

I ran into this with sqlite3 db, using Django 1.6. Here are the solutions.

  1. django.middleware.transaction.TransactionMiddleware has been deprecated. If you don’t have this in your settings.py file, you should not get the error.

  2. Accidentally, I found that including ATOMIC_REQUESTS: True works around the error if you had left django.middleware.transaction.TransactionMiddleware in your middlewares list.

E.g.

DATABASES = {
  'default': {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': 'sqlite3-db',
    'ATOMIC_REQUESTS': True
  }
}
πŸ‘€Overclocked

14πŸ‘

I had the same issue in my forwards migration (interestingly, didn’t happen in my backwards migration), and don’t have TransactionMiddleware in my settings. My workaround was to avoid using the get_or_create method and instead do the same thing more verbosely. From the 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()

You can then create your own pseudo-get_or_create method like this:

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

Which you can use by doing the following

obj = fake_get_or_create(Person, first_name='John', last_name='Lennon')
πŸ‘€johnboiles

7πŸ‘

I ran into the same problem when using sqlite3. I found out that I was using transaction.commit_on_success. On changing that to transaction.atomic(), the problem was resolved.

1πŸ‘

I believe the error is due to limitations of Sqlite3. To resolve this, I had to switch from Sqlite3 to a more robust database engine like postgrsql_psycopg2.

The code throwing the error (transaction.py:244) provides a clue in the comment:

        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'.")

Looking at the latest South Documentation (0.8.4) sheds more light on issues with Sqlite3: http://south.readthedocs.org/en/latest/databaseapi.html#database-specific-issues

SQLite doesn’t natively support much schema altering at all, but South has workarounds to allow deletion/altering of columns. Unique indexes are still unsupported, however; South will silently ignore any such commands.

In my case, I have unique indexes in my models which appear to be unsupported.

πŸ‘€gabrtv

1πŸ‘

add these to your migrations

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

and it will set the auto commit to true for migrations πŸ™‚

πŸ‘€Yousuf Jawwad

Leave a comment