Перенос приложения Django только в альтернативную базу данных

#python #django

#python #django

Вопрос:

У меня есть проект Django с несколькими приложениями. Я хочу, чтобы одно из этих приложений (с именем warehouse ) переходило к определенной базе данных (также с именем warehouse ), но, похоже, это работает не так, как я ожидаю. Когда я переношу это приложение из командной строки ( python manage.py migrate warehouse ), я получаю сообщение об успешном завершении:

 >>> python manage.py migrate warehouse
Operations to perform:
  Apply all migrations: warehouse
Running migrations:
  Applying warehouse.0001_initial... OK
  

Миграция отображается в default базе данных, что неверно, но таблицы не создаются, что правильно. Если я изменю команду на следующую:

 >>> python manage.py migrate warehouse --database=warehouse
  

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

Вот моя настройка:

Настройка базы данных в settings.py

 DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'projects',
        'USER': 'myuser',
        'PASSWORD': 'mypassword',
        'HOST': 'localhost',
        'PORT': '5432',
    },
    'warehouse': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': 'projects-warehouse',
        'USER': 'otheruser',
        'PASSWORD': 'otherpassword',
        'HOST': 'localhost',
        'PORT': '5432',
    },
}

DATABASE_ROUTERS = ['warehouse.dbrouter.WarehouseRouter', 'base.dbrouter.BaseRouter']
  

dbrouter.py [Приложение для хранилища]

 class WarehouseRouter:
    def db_for_read(self, model, **hints):
        if(model._meta.app_label == 'warehouse'):
            return 'warehouse'

        return None

    def db_for_write(self, model, **hints):
        if(model._meta.app_label == 'warehouse'):
            return 'warehouse'

        return None

    def allow_relation(self, obj1, obj2, **hints):
        if(obj1._meta.app_label == 'warehouse' and
           obj2._meta.app_label == 'warehouse'):
            return True

        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if(app_label == 'warehouse'):
            return db == 'warehouse'

        return None
  

dbrouter.py [Все другие приложения]

 class BaseRouter:
    def db_for_read(self, model, **hints):
        return 'default'

    def db_for_write(self, model, **hints):
        return 'default'

    def allow_relation(self, obj1, obj2, **hints):
        if(obj1._state.db == "default" and obj2._state.db == "default"):
            return True

        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        return db == 'default'
  

Комментарии:

1. Это ожидаемое поведение. Читать это . Вы не можете настроить его на получение ошибки, если только вы не определили default базу данных, которая заставляет вас всегда запускаться с --database опцией.

2. Я никак не могу настроить маршрутизатор базы данных на отклонение обращения warehouse on default ? Документация, на которую вы ссылаетесь, кажется, намекает, что это должно быть возможно.

3. Нет, просто всегда выполняйте миграции для всех ваших баз данных. С настройками вашего маршрутизатора будут выполнены правильные миграции в правильную базу данных.

Ответ №1:

Вы используете базы данных для сохранения своих моделей, а Django также использует базы данных для отслеживания миграций, и если вы не укажете какое-либо имя базы данных при переносе приложения, Django будет использовать "default" базу данных для хранения метаданных миграции.

Это ожидаемое поведение. Когда вы делаете:

 >>> python manage.py migrate warehouse
  

Django сохраняет миграции в базу данных по умолчанию, и таблицы сохраняются в warehouse базе данных только из-за WarehouseRouter .

и затем, когда вы делаете:

 >>> python manage.py migrate warehouse --database=warehouse
  

Тогда Django «знает», что ему нужно перенести миграции в другое место, в базу данных по умолчанию.

Я не тестировал, но я думаю, что это сработало бы (миграция и создание таблиц, без записи и чтения в / из моделей) даже без WarehouseRouter .

Комментарии:

1. Я чувствую, что требуется маршрутизатор. Я специально не хочу, чтобы warehouse данные отображались в моей default базе данных.