複数のデータベース

ここでは、Djangoがサポートする複数データベースの扱いについて説明します。残りのDjangoのドキュメントの大部分は、あなたが一つのデータベース扱うことを前提としています。複数のデータベースを使いたいなら、いくつかの追加ステップを踏む必要があります。

参考

複数のデータベースを使用したテストに付いての情報は、マルチデータベースのサポート を参照してください。

データベースを定義する

Django でデータベースを使う最初のステップは、利用するデータベースサーバーを Django に教えることです。これは、DATABASES の設定で行います。この設定は、データベースへのエイリアスです。Django を通してデータベースを参照するためのデータベースエイリアスを、辞書にマッピングします。この辞書の設定の詳細は、DATABASES ドキュメントで説明しています。

データベースには、選択した任意のエイリアスを付けることができます。しかし、エイリアス default は特別な意味があります。Django は、他のデータベースが選択されていない場合、default というエイリアスを持つデータベースを使用します。

以下に示すのは、2つのデータベース、すなわちデフォルトの PostgreSQL データベースと users という名前の MySQL データベースを定義した settings.py スニペットの例です。

DATABASES = {
    "default": {
        "NAME": "app_data",
        "ENGINE": "django.db.backends.postgresql",
        "USER": "postgres_user",
        "PASSWORD": "s3krit",
    },
    "users": {
        "NAME": "user_data",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_user",
        "PASSWORD": "priv4te",
    },
}

default データベースという概念がプロジェクトのコンテキストで意味をなさない場合、使用したいデータベースを注意深く常に指定する必要があります。Django は default データベースエントリーが定義されていることを要求しますが、使用しない場合はパラメータのディクショナリを空白のままにできます。これを行うには、使用している contrib とサードパーティを含むすべてのアプリのモデルで DATABASE_ROUTERS をセットアップしなければなりません。以下は、default エントリーを意図的に空のままにして、2つの default ではないデータベースを定義している settings.py スニペットの例です。

DATABASES = {
    "default": {},
    "users": {
        "NAME": "user_data",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_user",
        "PASSWORD": "superS3cret",
    },
    "customers": {
        "NAME": "customer_data",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_cust",
        "PASSWORD": "veryPriv@ate",
    },
}

DATABASES 設定で定義されていないデータベースへのアクセスを試みた場合、Django は django.utils.connection.ConnectionDoesNotExist 例外を発生されます。

データベースを同期する

migrate 管理コマンドは一度に一つのデータベースに対して動作します。デフォルトでは default データベース上で動作しますが、 --database オプションを指定することで、別のデータベースを同期させることができます。つまり、上記の最初の例ですべてのモデルをすべてのデータベースに同期させるには、次のように呼び出します:

$ ./manage.py migrate
$ ./manage.py migrate --database=users

すべてのアプリケーションを特定のデータベースに同期させたくない場合には、特定のモデルの利用を制限するポリシーを実装した データベース ルーター を定義できます。

上記の2番目の例のように、 default データベースを空のままにしている場合、 migrate を実行するときは毎回データベース名を指定する必要があります。データベース名を省略するとエラーになります。2番目の例では次のようになります:

$ ./manage.py migrate --database=users
$ ./manage.py migrate --database=customers

他の管理コマンドを使用する

データベースとやり取りする他のほとんどの django-admin コマンドは migrate と同じ方法で動作します ― これらは一度に一つのデータベース上でのみ動作し、使用するデータベースを制御するために --database を使用します。

このルールの例外は makemigrations コマンドです。このコマンドは新しいマイグレーションを作成する前に、データベース内のマイグレーション履歴を検証して、既存のマイグレーションファイルの問題 (マイグレーションファイル自体の編集によって起こるものを含む) を検出します。デフォルトでは default データベースのみをチェックしますが、 routers がインストールされている場合には allow_migrate() メソッドを参照します。

自動的なデータベースのルーティング

複数のデータベースを使用する最も簡単な方法は、データベースのルーティングスキームを設定することです。デフォルトのルーティングスキームでは、オブジェクトは元のデータベースに ''くっついた'' まま保存されます (つまり、foo データベースから取得したオブジェクトは同じデータベースに保存されます)。デフォルトのルーティングスキームでは、データベースが指定されていない場合、すべてのクエリは default データベースにフォールバックします。

デフォルトのルーティングスキームを有効にするために何もする必要はありません -- すべての Django プロジェクトで「箱から出してすぐに」使えます。しかし、もっと面白いデータベース割り当ての動作を実装したければ、独自の データベース ルーターを定義してインストールできます。

データベース ルーター

データベース ルーターは、以下の 4 つのメソッドを提供するクラスです:

db_for_read(model, **hints)

model 型のオブジェクトの読み取り操作に使用するデータベースをサジェストします。

データベース操作がデータベースを選択する際に役立つ追加情報を提供できる場合、それは hints 辞書で与えられます。有効なヒントの詳細は 下記 を参照してください。

サジェストがない場合は None を返します。

db_for_write(model, **hints)

Model型のオブジェクトの書き込みに使用するデータベースをサジェストします。

データベース操作がデータベースを選択する際に役立つ追加情報を提供できる場合、それは hints 辞書で与えられます。有効なヒントの詳細は 下記 を参照してください。

サジェストがない場合は None を返します。

allow_relation(obj1, obj2, **hints)

もし obj1obj2 の間のリレーションが許可されるべきであれば True を、禁止されるべきであれば False を、ルーターの意見がなければ None を返します。これは純粋に検証操作であり、外部キーや多対多の操作で、2つのオブジェクト間でリレーションが許可されるべきかどうかを判断するために使用されます。

どのルーターも意見を持たない場合 (つまり、すべてのルーターが None を返す場合)、同じデータベース内のリレーションだけが許可されます。

allow_migrate(db, app_label, model_name=None, **hints)

エイリアス db を持つデータベース上でマイグレーション操作を実行できるかどうかを判定します。操作を実行すべき場合は True を、実行すべきでない場合は False を、ルーターが意見を持たない場合は None を返します。

位置引数 app_label はマイグレーションするアプリケーションのラベルです。

model_name はマイグレーションするモデルの model._meta.model_name (モデルの __name__ を小文字にしたもの) に設定されます。この値は RunPythonRunSQL 操作ではヒントを使用しない限り None です。

hints は特定の操作でルーターに追加情報を伝えるために使われます。

model_name がセットされている場合、通常 hints には 'model' というキーの下にモデルクラスが含まれます。これは 履歴上のモデル であり、カスタム属性、メソッド、マネージャを持たないことに注意してください。 _meta にのみ依存する必要があります。

この方法は、指定されたデータベース上のモデルの可用性を判断するためにも使用できます。

makemigrations は常にモデルの変更に対してマイグレーションを作成しますが、 allow_migrate()False を返した場合、 dbmigrate を実行すると、 model_name に対するマイグレーション操作はすべて警告なしにスキップされます。マイグレーションしているモデルに対して allow_migrate() の動作を変更すると、外部キーが壊れたり、テーブルが増えたり、テーブルがなくなったりする可能性があります。 makemigrations がマイグレーション履歴を確認するとき、マイグレーションが許可されていないデータベースはスキップされます。

ルーターはこれらのメソッドを 全て 提供する必要はありません -- 1 つ以上省略してもかまいません。もしメソッドの1つが省略された場合、 Django は関連するチェックを行う際にそのルーターをスキップします。

ヒント

データベースルーターが受け取ったヒントは、与えられたリクエストをどのデータベースが受け取るべきかを決定するために使うことができます。

現在のところ、提供される唯一のヒントは instance で、現在進行中の読み取りまたは書き込み操作に関連するオブジェクトのインスタンスです。これは保存されるインスタンスかもしれませんし、多対多の関係で追加されるインスタンスかもしれません。場合によっては、インスタンスヒントは全く提供されません。ルーターはインスタンスヒントの存在をチェックし、そのヒントを使用してルーティング動作を変更すべきかどうかを決定します。

ルーターを使用する

データベースルーターは DATABASE_ROUTERS 設定を使ってインストールします。この設定はクラス名のリストを定義し、それぞれがベースルーター (django.db.router) が使用するルーターを指定します。

ベースルーターは Django のデータベース操作で、データベースの使用量を割り当てるために使われます。クエリがどのデータベースを使うか知る必要があれば常に、ベースルーターを呼び出し、 モデルとヒント (もしあれば) を提供します。ベースルーターは、データベースのサジェストを返すルーターが現れるまで、順番に各ルータークラスを試します。ヒントを返すルーターがない場合、ベースルーターはヒントインスタンスの instance._state.db を試します。ヒントインスタンスが提供されなかった場合、または instance._state.dbNone の場合、ベースルーターは default データベースを割り当てます。

例としてのみ使用してください!

この例は、ルーターのインフラストラクチャを使用してデータベースの使用状況を変更する方法のデモを示すことだけを目的としています。ルーターの使用方法を紹介するために、いくつかの複雑な問題を意図的に無視しています。

この例は、myapp 内のモデルのいずれかに other データベースの外部にあるモデルとのリレーションが含まれている場合には機能しません。クロスデータベース リレーション を使うと、現時点では Django が処理できない参照整合性の問題が発生します。

プライマリ/レプリカ(一部のデータベースではマスター/スレーブと呼ばれる)構成も欠陥があります。レプリケーション・ラグ(書き込みがレプリカに伝搬するまでに時間がかかるために発生するクエリの不整合)を処理するソリューションを提供していません。また、トランザクションとデータベース利用戦略との相互作用も考慮されていません。

では、実際にはどうなのでしょうか?別のサンプル構成を考えてみましょう。1つは auth アプリケーション用で、他のアプリケーションはプライマリ/レプリカのセットアップを使用し、2つのリードレプリカを使用します。これらのデータベースを指定する設定は以下の通りです:

DATABASES = {
    "default": {},
    "auth_db": {
        "NAME": "auth_db_name",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_user",
        "PASSWORD": "swordfish",
    },
    "primary": {
        "NAME": "primary_name",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_user",
        "PASSWORD": "spam",
    },
    "replica1": {
        "NAME": "replica1_name",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_user",
        "PASSWORD": "eggs",
    },
    "replica2": {
        "NAME": "replica2_name",
        "ENGINE": "django.db.backends.mysql",
        "USER": "mysql_user",
        "PASSWORD": "bacon",
    },
}

次に、ルーティングを処理する必要があります。まず、 authcontenttypes アプリのクエリを auth_db に送信するルーターが必要です (auth モデルは ContentType にリンクされているので、同じデータベースに格納されている必要があります):

class AuthRouter:
    """
    A router to control all database operations on models in the
    auth and contenttypes applications.
    """

    route_app_labels = {"auth", "contenttypes"}

    def db_for_read(self, model, **hints):
        """
        Attempts to read auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return "auth_db"
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write auth and contenttypes models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return "auth_db"
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the auth or contenttypes apps is
        involved.
        """
        if (
            obj1._meta.app_label in self.route_app_labels
            or obj2._meta.app_label in self.route_app_labels
        ):
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure the auth and contenttypes apps only appear in the
        'auth_db' database.
        """
        if app_label in self.route_app_labels:
            return db == "auth_db"
        return None

また、他のすべてのアプリをプライマリ/レプリカ構成に送り、ランダムにレプリカを選んで読み込むルーターも必要です:

import random


class PrimaryReplicaRouter:
    def db_for_read(self, model, **hints):
        """
        Reads go to a randomly-chosen replica.
        """
        return random.choice(["replica1", "replica2"])

    def db_for_write(self, model, **hints):
        """
        Writes always go to primary.
        """
        return "primary"

    def allow_relation(self, obj1, obj2, **hints):
        """
        Relations between objects are allowed if both objects are
        in the primary/replica pool.
        """
        db_set = {"primary", "replica1", "replica2"}
        if obj1._state.db in db_set and obj2._state.db in db_set:
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        All non-auth models end up in this pool.
        """
        return True

最後に、設定ファイルに以下を追加します (path.to. はルーターが定義されているモジュールの実際のPythonパスで置き換えてください):

DATABASE_ROUTERS = ["path.to.AuthRouter", "path.to.PrimaryReplicaRouter"]

ルーターが処理される順番は重要です。ルーターは DATABASE_ROUTERS 設定にリストされている順番にクエリされます。この例では、 AuthRouterPrimaryReplicaRouter よりも先に処理され、その結果、 auth のモデルに関する決定が他の決定よりも先に処理されます。もし DATABASE_ROUTERS 設定が2つのルーターを他の順番でリストしていた場合、 PrimaryReplicaRouter.allow_migrate() が最初に処理されます。PrimaryReplicaRouter実装のキャッチオール特性により、すべてのデータベースですべてのモデルが利用可能になります。

このセットアップをインストールし、 データベースを同期する に従って全てのデータベースをマイグレーションした状態で、Django のコードを実行してみましょう:

>>> # This retrieval will be performed on the 'auth_db' database
>>> fred = User.objects.get(username="fred")
>>> fred.first_name = "Frederick"

>>> # This save will also be directed to 'auth_db'
>>> fred.save()

>>> # These retrieval will be randomly allocated to a replica database
>>> dna = Person.objects.get(name="Douglas Adams")

>>> # A new object has no database allocation when created
>>> mh = Book(title="Mostly Harmless")

>>> # This assignment will consult the router, and set mh onto
>>> # the same database as the author object
>>> mh.author = dna

>>> # This save will force the 'mh' instance onto the primary database...
>>> mh.save()

>>> # ... but if we re-retrieve the object, it will come back on a replica
>>> mh = Book.objects.get(title="Mostly Harmless")

この例では auth アプリのモデルとのやりとりを処理するルーターと、その他のアプリとのやりとりを処理するルーターを定義しています。もし default データベースを空のままにしていて、他に指定されていないすべてのアプリを処理するためのデータベースルーターを定義したくない場合は、マイグレーションする前に INSTALLED_APPS にあるすべてのアプリの名前をルーターで処理する必要があります。1つのデータベースにまとめなければならないcontribアプリについては contribアプリの振る舞い を参照してください。

データベースを手動で選択する

Django は、コード中でデータベースの利用を完全に制御できる API も提供し ています。手動で指定したデータベースの割り当てが、データベースルーターが割り当てたデー タベースよりも優先されます。

QuerySet のためのデータベースを手動で選択する

QuerySet の "チェーン" のどの時点でも、 QuerySet のデータベースを選択できます。指定したデータベースを使用する別の QuerySet を取得するには、 QuerySetusing() を呼び出します。

using() は引数を1つ取り、クエリを実行したいデータベースのエイリアスを指定します。例えば次のようにします:

>>> # This will run on the 'default' database.
>>> Author.objects.all()

>>> # So will this.
>>> Author.objects.using("default")

>>> # This will run on the 'other' database.
>>> Author.objects.using("other")

save() のためのデータベースを選択する

データを保存するデータベースを指定するには Model.save()using キーワードを使用します。

例えば、 legacy_users データベースにオブジェクトを保存するには、次のようにします:

>>> my_object.save(using="legacy_users")

もし using を指定しなければ、 save() メソッドはルーターが割り当てたデフォルトのデータベースに保存します。

オブジェクトを1つのデータベースからもう1つのデータベースに移動する

あるデータベースにインスタンスを保存した場合、インスタンスを新しいデータベースにマイグレーションする方法として save(using=...) を使いたくなるかもしれません。しかし、適切な手順を踏まないと、これは予期せぬ結果を招く可能性があります。

以下の例を考えてみてください。

>>> p = Person(name="Fred")
>>> p.save(using="first")  # (statement 1)
>>> p.save(using="second")  # (statement 2)

statement 1 では、新しい Person オブジェクトが first データベースに保存されます。この時、 p にはプライマリキーがないので、 Django は SQL の INSERT 文を発行します。これによりプライマリキーが作成され、 Django はそのプライマリキーを p に割り当てます。

statement 2 で保存が行われるとき、 p はすでにプライマリキーの値を持っていて、 Django は新しいデータベースでそのプライマリキーを使おうとします。もしプライマリキーの値が second のデータベースで使われていなければ、何の問題もありません -- オブジェクトは新しいデータベースにコピーされます。

しかし、 p のプライマリキーがすでに second データベースで使用されている場合は、 p が保存されたときに second データベースの既存のオブジェクトが上書きされます。

これを回避するには2つの方法があります。1つ目の方法は、インスタンスのプライマリキーをクリアすることです。オブジェクトにプライマリキーがない場合、 Django はそのオブジェクトを新しいオブジェクトとして扱い、 second データベースのデータが失われるのを防ぎます:

>>> p = Person(name="Fred")
>>> p.save(using="first")
>>> p.pk = None  # Clear the primary key.
>>> p.save(using="second")  # Write a completely new object.

2 つ目のオプションは、 save()force_insert オプションをつけて、 Django が SQL の INSERT を行うようにすることです:

>>> p = Person(name="Fred")
>>> p.save(using="first")
>>> p.save(using="second", force_insert=True)

これにより、 Fred という人物は両方のデータベースで同じプライマリキーを持つことになります。もしそのプライマリキーがすでに second データベースで使用されている場合、保存しようとするとエラーが発生します。

削除が行われるデータベースを選択する

デフォルトでは、既存のオブジェクトを削除する呼び出しは、最初にオブジェクトを取得するために使用したのと同じデータベース上で実行されます。

>>> u = User.objects.using("legacy_users").get(username="fred")
>>> u.delete()  # will delete from the `legacy_users` database

モデルを削除するデータベースを指定するには、using キーワード引数を Model.delete() メソッドに渡します。この引数は、save()using キーワード引数と同じように機能します。

例えば、あるユーザーを legacy_users データベースから new_users データベースにマイグレーションする場合、以下のコマンドを使用します:

>>> user_obj.save(using="new_users")
>>> user_obj.delete(using="legacy_users")

複数のデータベースでマネージャを使う

デフォルト以外のデータベースにマネージャがアクセスできるようにするには、マネージャの db_manager() メソッドを使用します。

例えば、データベースにアクセスするカスタムマネージャメソッド User.objects.create_user() があるとします。 create_user() はマネージャメソッドであり、 QuerySet メソッドではないので、 User.objects.using('new_users').create_user() は実行できません。 (create_user() メソッドはマネージャである User.objects でのみ使用可能で、マネージャから派生した QuerySet オブジェクトでは使用できません)。解決策は、次のように db_manager() を使うことです:

User.objects.db_manager("new_users").create_user(...)

db_manager() は指定したデータベースに結び付けられたマネージャのコピーを返します。

複数のデータベースで get_queryset() を使う

マネージャ上で get_queryset() をオーバーライドする場合は、親メソッドを呼び出す (super() を使用する) か、マネージャの _db 属性 (使用するデータベースの名前を含む文字列) を適切に処理するようにしてください。

例えば、カスタム QuerySet クラスを get_queryset メソッドから返したい場合は、このようにします:

class MyManager(models.Manager):
    def get_queryset(self):
        qs = CustomQuerySet(self.model)
        if self._db is not None:
            qs = qs.using(self._db)
        return qs

Django の管理インタフェースで複数のデータベースを公開する

Django の admin は複数のデータベースを明示的にサポートしていません。ルーターチェーンで指定したデータベース以外のデータベース上のモデルに対して admin インタフェースを提供したい場合は、 admin が特定のデータベースをコンテンツに使うように指示するカスタム ModelAdmin クラスを書く必要があります。

ModelAdmin オブジェクトには、複数のデータベースのサポートのためのカスタマイズが必要な以下のメソッドがあります:

class MultiDBModelAdmin(admin.ModelAdmin):
    # A handy constant for the name of the alternate database.
    using = "other"

    def save_model(self, request, obj, form, change):
        # Tell Django to save objects to the 'other' database.
        obj.save(using=self.using)

    def delete_model(self, request, obj):
        # Tell Django to delete objects from the 'other' database
        obj.delete(using=self.using)

    def get_queryset(self, request):
        # Tell Django to look for objects on the 'other' database.
        return super().get_queryset(request).using(self.using)

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        # Tell Django to populate ForeignKey widgets using a query
        # on the 'other' database.
        return super().formfield_for_foreignkey(
            db_field, request, using=self.using, **kwargs
        )

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        # Tell Django to populate ManyToMany widgets using a query
        # on the 'other' database.
        return super().formfield_for_manytomany(
            db_field, request, using=self.using, **kwargs
        )

ここで示した実装はマルチデータベース戦略を実装したもので、指定されたタイプのオブジェクトはすべて特定のデータベースに保存されます (例えば、すべての User オブジェクトは other データベースに保存されます)。複数のデータベースをより複雑に使用する場合は、 ModelAdmin にその戦略を反映させる必要があります。

InlineModelAdmin オブジェクトも同じように扱うことができます。これらのオブジェクトには3つのカスタマイズされたメソッドが必要です:

class MultiDBTabularInline(admin.TabularInline):
    using = "other"

    def get_queryset(self, request):
        # Tell Django to look for inline objects on the 'other' database.
        return super().get_queryset(request).using(self.using)

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        # Tell Django to populate ForeignKey widgets using a query
        # on the 'other' database.
        return super().formfield_for_foreignkey(
            db_field, request, using=self.using, **kwargs
        )

    def formfield_for_manytomany(self, db_field, request, **kwargs):
        # Tell Django to populate ManyToMany widgets using a query
        # on the 'other' database.
        return super().formfield_for_manytomany(
            db_field, request, using=self.using, **kwargs
        )

モデル管理定義を書いたら、任意の Admin インスタンスに登録できます:

from django.contrib import admin


# Specialize the multi-db admin objects for use with specific models.
class BookInline(MultiDBTabularInline):
    model = Book


class PublisherAdmin(MultiDBModelAdmin):
    inlines = [BookInline]


admin.site.register(Author, MultiDBModelAdmin)
admin.site.register(Publisher, PublisherAdmin)

othersite = admin.AdminSite("othersite")
othersite.register(Publisher, MultiDBModelAdmin)

この例では2つの管理サイトを設定しています。最初のサイトでは AuthorPublisher オブジェクトが公開され、 Publisher オブジェクトにはその出版社が出版した書籍を示すインラインが表形式で表示されます。2番目のサイトでは、インラインを使わずに出版社だけを公開しています。

複数のデータベースで生のカーソルを使う

複数のデータベースを使用している場合、 django.db.connections を使用することで、特定のデータベースのコネクション (とカーソル) を取得できます。 django.db.connections は辞書のようなオブジェクトで、次のように、エイリアスを使って個別の接続を取得できます。

from django.db import connections

with connections["my_db_alias"].cursor() as cursor:
    ...

複数データベースの制約

データベースをまたぐリレーション

Djangoは現在、複数のデータベースにまたがる外部キーまたは多対多の関係をサポートしていません。もしモデルを異なるデータベースに分割するためにルーターを使用している場合、それらのモデルによって定義される外部キーおよび多対多の関係は、単一のデータベース内部に限定されなければなりません。

これは参照整合性のためです。2つのオブジェクト間のリレーションシップを維持するためには、Djangoはリレーション先オブジェクトのプライマリキーが有効であることを知る必要があります。プライマリキーが別のデータベースに格納されている場合、プライマリキーが有効かどうかを判断するのは容易ではありません。

Postgres、SQLite、Oracle、MySQLをInnoDBで使用している場合、これはデータベースの整合性レベルで強制されます。データベースレベルのキー制約は、検証できないリレーションの作成を防ぎます。

しかし、MySQL で MyISAM テーブルを使用している場合、参照整合性は強制されません。その結果、データベースの外部キーを「偽装」できるかもしれません。しかし、この設定は Django では公式にはサポートされていません。

contribアプリの振る舞い

いくつかのcontribアプリはモデルを含み、いくつかのアプリは他のアプリに依存しています。データベースをまたいだリレーションシップは不可能であるため、データベースをまたいでこれらのモデルを分割する方法に制限が生じます:

  • contenttypes.ContentType, sessions.Session, sites.Site はいずれも、適切なルーターがあれば、どのデータベースにも格納できます。

  • UserGroupPermissionauth モデルは ContentType とリンクしているため、 ContentType と同じデータベースに保存する必要があります。

  • adminauth に依存しているので、そのモデルは auth と同じデータベースに置く必要があります。

  • flatpagesredirectssites に依存しているため、それらのモデルは sites と同じデータベースに置く必要があります。

さらに、下記のようないくつかのオブジェクトは migrate がデータベースにテーブルを作成した直後に自動的に作成されます:

  • デフォルトの Site

  • 各モデル (そのデータベースに保存されていないものも含む) の ContentType

  • 各モデル(そのデータベースに保存されていないものも含む)の Permission

複数のデータベースを使用する通常のセットアップでは、これらのオブジェクトを複数のデータベースに持つことは有益ではありません。通常のセットアップには、プライマリ/レプリカや外部データベースへの接続などがあります。そのため、これら3つのモデルを1つのデータベースだけに同期させることができる データベースルーター を書くことを推奨します。複数のデータベースのテーブルを必要としないcontribやサードパーティアプリにも同じアプローチを使用してください。

警告

コンテンツ・タイプを複数のデータベースに同期する場合、データベース間でプライマリ・キーが一致しない可能性があることに注意してください。その結果、データが破損したり、データが失われたりする可能性があります。

Back to Top