How to make Django management command not open a transaction?
Asked Answered
T

1

7

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

Talishatalisman answered 18/3, 2013 at 17:13 Comment(0)
A
6

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!

Aperture answered 19/3, 2013 at 10:12 Comment(2)
Thanks. Was trying and so far couldn't avoid django to open a connection on a management command. Your solution even though its not optimal its an workaround that works as it opens a different connection. Voting you upTalishatalisman
Added a second option above... still not ideal though.Aperture

© 2022 - 2024 — McMap. All rights reserved.