#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
ondefault
? Документация, на которую вы ссылаетесь, кажется, намекает, что это должно быть возможно.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
базе данных.