james mckay dot net
because there are few things that are less logical than business logic

Django custom manage.py commands not committing transactions?

Over the weekend I was doing a bit more Django development, and I ran into a rather strange problem. I had written a custom command for manage.py whose last task was to update some rows in a couple of database tables using some raw SQL commands. Strangely, the changes weren’t showing up when I looked at the data in MySQL Query Browser afterwards. Even more strangely, when I copied and pasted the raw SQL and ran it in Query Browser, it worked fine.

A little bit of extra code revealed that the SQL commands were being run, which absolutely screamed that the code was being run in a transaction that wasn’t getting committed. Fixing it was simply a case of adding these two lines at the end of my custom command:

from django.db import transaction
transaction.commit_unless_managed()

I’m not sure whether this is a bug or a feature. Django’s default transaction behaviour — in HTTP requests at any rate — is the autocommit model: every change you make is automatically committed as soon as it is run. I’d have thought it would be the same in management commands, but clearly it is doing something rather different here. If anyone can enlighten me, I’d be interested to know.