3

I am on Django 1.6, writing a unit test using the built-in client, trying to test a login call. The code below summarizes it. This is run against SQLite3 database. When I run this, I get the following error when the self.client.login() method is called:

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

It tried to set:

'OPTIONS': {
    'autocommit': True,
}

in the database section of my settings.py file, but that didn't help and generated a different error message:

KeyError: 'ENGINE'

Any help with this would be greatly appreciated. My code follows:

def testShouldRedirectToDashboardAfterSuccessfulLogin(self):
    from django.contrib.auth.models import User
    u = User.objects.create_user(
        username="a@b.cz",
        password='aaaaa',
        email="a@b.cz"
    )

    self.assertTrue(self.client.login(
        username='a@b.cz',
        password='aaaaa'
    ))
pkout
  • 6,430
  • 2
  • 45
  • 55
  • Also, the test method is in a class inherited from django_nose.FastFixtureTestCase. – pkout Dec 16 '13 at 00:05
  • possible duplicate of [Django 1.6 TransactionManagementError: database doesn't behave properly when autocommit is off](http://stackoverflow.com/questions/20039250/django-1-6-transactionmanagementerror-database-doesnt-behave-properly-when-aut) – juliocesar Mar 26 '14 at 17:14

2 Answers2

3

I found a solution. I needed to add this at the beginning of the test method call and, thereby, wrap the whole test method call in this to turn autocommit on:

def testShouldRedirectToDashboardAfterSuccessfulLogin(self):
    from django.db import transaction
    transaction.set_autocommit(True)
    try:
        from django.contrib.auth.models import User
        u = User.objects.create_user(
            username="a@b.cz",
            password='aaaaa',
            email="a@b.cz"
        )

        self.assertTrue(self.client.login(
            username='a@b.cz',
            password='aaaaa'
        ))
    finally:
        u.delete()
        transaction.set_autocommit(False)

I hope this helps someone. I am still a bit confused why I had to do this because the documentation says that in Django 1.6, "Autocommit is initially turned on. If you turn it off, it’s your responsibility to restore it." If you have any valuable info to add to this, feel welcome to comment below. I'll make sure to upvote your comment if it sheds more light on this.

pkout
  • 6,430
  • 2
  • 45
  • 55
1

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
  • 1,187
  • 1
  • 11
  • 22
  • Thanks! I'll try your solution tonight when I get home and accept it if it works on my end. Your solution is better than my workaround. – pkout Dec 20 '13 at 17:43
  • 1
    Even when maybe this is a usefull answer, instead of [answer the same twice](http://stackoverflow.com/a/20707924/2343488) you should flag question as [possible duplicate](http://stackoverflow.com/q/20039250/2343488) or at lease post a comment with the reference. – juliocesar Mar 26 '14 at 17:18
  • This solution didn't work for me when running unittests (django 1.6, in-memory sqlite db for tests) – bruno desthuilliers Dec 26 '14 at 10:10