3

Well, after reading the doc https://docs.djangoproject.com/en/1.6/topics/db/multi-db/

I understand the way that developer can manually select database for selecting, saving and deleting. My question is that is there a more easy way for doing that?

I mean does django have something like its transaction management?

with transaction.atomic():
    do_something()

So all the code under a particular section are in one transaction that talking to one particular database, like

with using(default):
    do_something()

If django doesn't have this kind of wrapper, is there any good way to achieve what I described?

Jerry Meng
  • 1,466
  • 3
  • 21
  • 40
  • This might help you: http://stackoverflow.com/questions/21861207/is-transaction-atomic-same-as-transaction-commit-on-success – Aswin Murugesh Feb 06 '15 at 20:59

1 Answers1

0

I don't believe there is. You could set the DATABASES setting to a custom dict-like class that can change the default, i.e.:

from threading import local

class DatabaseSettings(dict):
    def __init__(self, db, *args, **kwargs):
        super(DatabaseSettings, self).__init__(*args, **kwargs)
        self._default = local()
        self._default.db = db

    def set_database(self, db):
        self._default.db = db

    def __getitem__(self, name):
        if name == DEFAULT_DB_ALIAS and self._default.db:
            name = self._default.db
        return super(DatabaseSettings, self).__getitem__(name)


from django.conf import settings
from django.utils import six
from django.db import connections, DEFAULT_DB_ALIAS


class UseDatabase(object):
    def __init__(self, db):
        self.db = db

    def __enter__(self):
        settings.DATABASES.set_database(self.db)
        conn = getattr(connections._connections, self.db, None)
        if conn:
            setattr(connections._connections, DEFAULT_DB_ALIAS, conn)

    def __exit__(self, exc_type, exc_value, traceback):
        settings.DATABASES.set_database(None)
        if exc_type:
            six.reraise(exc_type, exc_value, traceback)

connections._connections is already thread-local, so this should be thread-safe. Please double check though, as I am far from an expert on multi-threading.

Now you can use with UseDatabase('<name>'): to specify a different database as a default for that block. This won't change the behaviour of code that explicitly uses a different database.

This code is far from complete but it should give you a start. Make sure that you actually save and restore the old default connection, and maybe it is a good idea to support nested context managers.

knbk
  • 52,111
  • 9
  • 124
  • 122