2016年11月20日日曜日

django で複数のデータベースを利用する

特定のアプリケーションの場合のみデータベースを変更したい場合、データベースルータを使用する。

まず、アクセス対象のデータベースを settings.py に記載する。
ここでは、通常(default)のデータベースと、特定のアプリケーションで利用するデータベース(nextdb)を定義した。
なお、以下の例では特定のアプリケーションを app としている。
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    },
    'nextdb': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'nextdb.sqlite3'),
    }
}
次に、データベースの切り替え条件を定義したルータの情報を記載する。なお、ここでは、project/router.py として作成する。
class Router(object):
    def db_for_read(self, model, **hints):
        if model._meta.app_label == "app":
            return "nextdb"
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label == "app":
            return "nextdb"
        return None

    def allow_relation(self, obj1, obj2, **hints):
        if obj1._meta.app_label == "app" and obj2._meta.app_label == "app":
            return True
        elif "app" not in [obj1._meta.app_label, obj2._meta.app_label]:
            return True
        return None

    def allow_migrate(self, db, app_label, model=None, **hints):
        if app_label == "app":
            return db == "nextdb"
        else:
            return db == "default"
db_for_read および db_for_write は、与えられた model のアクセス先データベースを返す関数である。なお、戻り値が None の場合は、DATABASES の default で定義したデータベースが採用される。

allow_relation は、外部キーなどの設定の際、オブジェクト間でのリレーション可否を判定するための関数である。また、allow_migrate は、該当モデルとデータベースとの同期可否を定義する。

上記のすべての関数を定義する必要はなく、必要なものを定義することになる。

最後に settings.py にルータ情報を登録する。
DATABASE_ROUTERS = ['router.Router']
例として、appアプリケーションのモデル(app/model.py)と、その他のアプリケーションで共通させるモデル(core/model.py)を以下のように定義する。
[app/model.py]

from django.db import models

class Organization(models.Model):
    organization_cd = models.CharField(max_length=5)
    name = models.CharField(max_length=20)

    def __unicode__(self):
        return self.name

    class Meta:
        ordering = ["organization_cd"]


class User(models.Model):
    staff_cd = models.CharField(max_length=7)
    name = models.CharField(max_length=15)
    organization = models.ForeignKey(Organization)
[core/model.py]

from django.db import models

class User(models.Model):
    cd = models.CharField(max_length=7)
    name = models.CharField(max_length=15)

    def __str__(self):
        return "%s %s" % (self.cd, self.name)
双方とも管理者画面からアクセスすると、2つのデータベースが作成されていることが確認できる。

0 件のコメント:

コメントを投稿