読者です 読者をやめる 読者になる 読者になる

Djangoで複数DBを取り扱うためのメモ

以下方法は自分では試してないが、メモとして残しておく。暫定での対応らしい。
Django本体での複数DB対応は■Alexさん■ががんばっているようだ。まだ完成していないもよう。
原文はこちら。

models.py

from project.app.managers import *

class Db1Model(models.Model):
    _default_manager = MultiDBManager('db1')
    objects = MultiDBManager('db1')
    db = 'db1'

    class Meta:
        abstract = True

# then for all models that use db1:
class MyModelFromDb1(Db1Model):
    ...

class Db2Model(models.Model):
    _default_manager = MultiDBManager('db2')
    objects = MultiDBManager('db2')
    db = 'db2'

    class Meta:
        abstract = True

# ditto for models in db2
class MyModelFromDb2(Db2Model):
    ...

managers.py

from django.db import models
from django.conf import settings
from django.db.models import sql
from django.db.transaction import savepoint_state
from django.core import signals

try:
    import thread
except ImportError:
    import dummy_thread as thread

_connections  = {}

def close_connection(**kwargs):
    global _connections
    for connection in _connections.itervalues():
        connection.close()
    _connections = {}
signals.request_finished.connect(close_connection)

class MultiDBManager(models.Manager):
    def __init__(self, database, *args, **kwargs):
        self.database = database
        self.use_for_related_fields = True
        super(MultiDBManager, self).__init__(*args, **kwargs)

    def get_query_set(self):
        qs = super(MultiDBManager, self).get_query_set()
        qs.query.connection = self.get_db_wrapper()
        return qs

    def get_db_wrapper(self):
        if not self.database:
            from django import connection
            return connection
        if not _connections.has_key(self.database):
            settings_dict = settings.DATABASES[self.database]
            backend = __import__('django.db.backends.%s.base' %
settings_dict['DATABASE_ENGINE'], {}, {}, ['base'])
            backup = {}
            for key, value in settings_dict.iteritems():
                backup[key] = getattr(settings, key)
                setattr(settings, key, value)
            wrapper = backend.DatabaseWrapper()
            wrapper._cursor(settings)
            _connections[self.database] = wrapper
            for key, value in backup.iteritems():
                setattr(settings, key, value)
        return _connections[self.database]

    def _insert(self, values, return_id=False, raw_values=False):
        query = sql.InsertQuery(self.model, self.get_db_wrapper())
        query.insert_values(values, raw_values)
        ret = query.execute_sql(return_id)
        query.connection._commit()
        thread_ident = thread.get_ident()
        if thread_ident in savepoint_state:
            del savepoint_state[thread_ident]
        return ret

settings.py:

DBコネクションの設定

DATABASE_ENGINE = 'mysql'
DATABASE_NAME = 'db1'
DATABASE_USER = 'auser'
DATABASE_PASSWORD = 'somepassword'
DATABASE_HOST = ''
DATABASE_PORT = ''

DATABASES = dict(
    db1 = dict(
        DATABASE_ENGINE=DATABASE_ENGINE,
        DATABASE_NAME=DATABASE_NAME,
        DATABASE_USER=DATABASE_USER,
        DATABASE_PASSWORD=DATABASE_PASSWORD,
        DATABASE_HOST=DATABASE_HOST,
        DATABASE_PORT=DATABASE_PORT,
    ),
    db2 = dict(
        DATABASE_ENGINE="mysql",
        DATABASE_NAME='db2',
        DATABASE_USER='anotheruser',
        DATABASE_PASSWORD='password',
        DATABASE_HOST='',
        DATABASE_PORT='',
    ),
)
まとめ
It seems to have worked for me so far. Obviously this is not a long
term solution, just something to get by with until Alex's code is
ready =)

訳:Alexががんばっているので、それまでの暫定コードです。

以下のページも見ると、参考になる。
[1] http://code.djangoproject.com/ticket/1142#comment:65
[2] http://www.eflorenzano.com/blog/post/easy-multi-database-support-django/