Подтвердить что ты не робот

Django - как указать базу данных для модели?

Можно ли указать, что модель (или приложение, даже) должна использовать только одну конкретную базу данных?

Я работаю с устаревшей базой данных, которую я не хочу менять. У меня есть две базы данных: "default" - это sqlite, который можно использовать для администратора и т.д., И для старого. Я использовал inspectdb для создания модели для (части) устаревшей базы данных, и она имеет managed = False. Но есть ли способ указать в самой модели, что он применим только к конкретной базе данных?

Я вижу, что вы можете указать using=databasename в некоторых наборах запросов и т.д., но это не подходит для таких вещей, как Databrowse (и, возможно, также общие представления?). Возможно, это краткий обзор Databrowse, что вы не можете указать базу данных, но это просто похоже на правильное место, чтобы указать, что это модель...

Тогда я подумал, может быть, ответ заключается в написании пользовательского менеджера моделей, который относится только к моей старой базе данных, - но в документах не упоминается ничего подобного.

Есть ли у меня другая ментальная модель того, как несколько баз данных могут быть использованы, в мир Django?

4b9b3361

Ответ 1

Насколько я знаю, вы не можете напрямую указывать базу данных с моделью, поскольку это могло бы помешать тому, чтобы приложение никогда не использовалось повторно, но из того, что я вижу в документах:

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

Ответ 2

Вы не можете указать базу данных для модели, но ее можно определить в пользовательском классе маршрутизатора.

# 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': {
        ....
    }
}

Ответ 3

Я обнаружил, что вы можете довольно просто направлять модели с помощью этого менеджера:

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 для этого.