web-dev-qa-db-ja.com

Django-モデルのデータベースを指定する方法は?

モデル(またはアプリ)が特定のデータベースを1つだけ使用するように指定する方法はありますか?

変更したくないレガシーデータベースを使用しています。私は2つのデータベースを持っています-「デフォルト」はadminなどに使用できるsqliteデータベースとレガシーデータベースです。 inspectdbを使用してレガシーデータベース(の一部)のモデルを作成しましたが、managed = Falseがあります。しかし、モデル自体で、特定のデータベースにのみ適用されることを指定する方法はありますか?

一部のクエリセットなどでusing=databasename を指定できますが、これは Databrowse (および場合によってはジェネリックビュー)のようなものには適していません。データベースを指定できないのはDatabrowseの欠点かもしれませんが、それを指定するのに適切な場所はモデルのようです...

それから私はおそらく答えは私のレガシーデータベースのみを参照するカスタム モデルマネージャー を書くことだと思いました-しかしドキュメントはそのようなことについて何も言及していません。

複数のデータベースがどのように使用されるかについて、Djangoの世界とは異なるメンタルモデルがありますか?

28
pfctdayelise

私の知る限り、モデルでデータベースを直接指定することはできません。これは、アプリが再利用できなくなるためですが、ドキュメントで確認できることからです。

https://docs.djangoproject.com/en/1.8/topics/db/multi-db/

12
Horst Gutmann

モデルのデータベースを指定することはできませんが、カスタムDBルータークラスでデータベースを定義することはできます。

# app/models.py
class SomeModel(models.Model):
    ...

# app/dbrouters.py
from app.models import SomeModel
...
class MyDBRouter(object):

    def db_for_read(self, model, **hints):
        """ reading SomeModel from otherdb """
        if model == SomeModel:
            return 'otherdb'
        return None

    def db_for_write(self, model, **hints):
        """ writing SomeModel to otherdb """
        if model == SomeModel:
            return 'otherdb'
        return None


# app/settings.py
DATABASE_ROUTERS = ('app.dbrouters.MyDBRouter',)
...
DATABASES = {
    ...
    'otherdb': {
        ....
    }
}
18

このマネージャーを使用すると、モデルを非常に簡単にルーティングできることがわかりました。

class SecondDbManager(models.Manager):
    def get_queryset(self):
        qs = super().get_queryset()

        # if `use_db` is set on model use that for choosing the DB
        if hasattr(self.model, 'use_db'):
            qs = qs.using(self.model.use_db)

        return qs

use_db='databasename'とこのマネージャーをモデルに追加するだけで、機能します。

または、さらに単純化するために、基本モデルを作成しました。

class SecondDbBase(models.Model):
    use_db = 'my_second_db'
    objects = SecondDbManager()

    class Meta:
        abstract = True

そしてこれであなたがする必要があるのはそのようにそれを拡張することです。の代わりに:

class Customer(models.Model):

これを行うだけで機能します:

class Customer(SecondDbBase):

PS。それがグッドプラクティスなのかベストソリューションなのかはわかりませんが、機能し、他のデータベースへのルーティングは簡単です:)

PSS。私はこれまでDjango(managed = False)によって管理されていないテーブルの読み取りと書き込みにのみこれらを使用したことがあるので、それらの移行を作成する必要がある場合、それが機能するかどうかはわかりません。そのためにDATABASE_ROUTERSを使用する必要があるかもしれません。

0
rain01