Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Django management command not open a transaction?

I'm writing a management command where I want to change the default isolation level. Django and my database will default it to "READ COMITTED" and I need it to be "READ UNCOMMITTED" only for this particular management command.

When running:

./manage.py my_command

I've noticed that Django by default opens a transaction with the default isolation level even if your command don't need any database connection:

from django.core.management.base import BaseCommand

class Command(BaseCommand):
    help = "Updates assortment data by refreshing the mviews"

    def handle(self, *args, **options):
        print "fdkgjldfkjgdlkfjgklj"

This behaviour doesn't fit my problem and I'm asking if there is a way of:

  • Write a management command where Django doesn't even touch the database leaving all the transaction control completely manual?

  • Write a management command where you can define transaction characteristics only for it?

Regards

like image 679
andrefsp Avatar asked Mar 18 '13 17:03

andrefsp


1 Answers

I came across your post on Facebook and thought I might be able to be some help :-)

You can specify database connections with read uncommitted with the following database settings in your settings.py:

DATABASES: {
    'default': {...}
    'uncommitted_db': {
        'ENGINE': ...
        'NAME': ...
        'USER': '...',
        'PASSWORD': '...',
        'HOST': '...', 
        'OPTIONS': {
            'init_command': 'SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED'  #MySQL
            'init_command': 'SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED' #Postgres
        }
    }
}

With this in place you can access your non-transactional database connection using Django's normal multidatabase syntax:

Model.objects.using('uncommitted_db').all()

Of course, you might not want to have your non-transactional database connection globally available in your entire application, so you'd ideally want a way to have it only available during the execution of this management command. Unfortunately, management commands don't work like that: once you hit the handle method on the Command class, your settings.py has already been parsed and your database connections have already been created. If you can find a way to re-initialise Django with a new set of database settings after runtime, or having a logical split in your settings.py based on your launch conditions, like so:

import sys
if 'some_management_cmd' in sys.argv: 
    DATABASES['default']['OPTIONS']['init_command'] = 'SET TRANSACTION...'

this could work, but is pretty horrible!

like image 170
majackson Avatar answered Sep 18 '22 12:09

majackson