Как использовать несколько баз данных в Django с пустым 'default'?

Я пытаюсь сделать проект с несколькими базами данных в Django. Но у меня возникают проблемы с правильной миграцией моих моделей в соответствующую базу данных.

Я использую учебник "Написание вашего первого приложения Django" в качестве отправной точки; итак ... Я написал следующие маршрутизаторы базы данных; этот для приложения 'polls':

class PollsRouter:

route_app_labels = {'polls'}

def db_for_read(self, model, **hint):
    if model._meta.app_label == 'polls':
        return 'Polls'
    return None

def db_for_rite(self, model, **hint):
    if model._meta.app_label == 'polls':
        return 'Polls'
    return None

def allow_relation(self, obj1, obj2, **hint):
    if (
        obj1._meta.app_label == 'polls' or
        obj2._meta.app_label == 'polls'
    ):
        return True
    return None

def allow_migrates(self, db, app_label, model_name=None, **hints):
    if app_label == 'polls':
        return db == 'Polls'
    return None

Также класс маршрутизатора для приложения 'devices':

class DevicesRouter:

route_app_labels = {'devices'}

def db_for_read(self, model, **hint):
    if model._meta.app_label == 'devices':
        return 'CTS_ER_BD'
    return None

def db_for_rite(self, model, **hint):
    if model._meta.app_label == 'devices':
        return 'CTS_ER_BD'
    return None

def allow_relation(self, obj1, obj2, **hint):
    if (
        obj1._meta.app_label == 'devices' or
        obj2._meta.app_label == 'devices'
    ):
        return True
    return None

def allow_migrates(self, db, app_label, model_name=None, **hints):
    if app_label == 'devices':
        return db == 'CTS_ER_BD'
    return None

И, наконец, класс маршрутизатора для базы данных 'auth_user' (для нативных приложений Django)

class Auth_userRouter:

    route_app_labels = {'auth', 'contenttypes', 'admin', 'sessions'}

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'Auth_user_db'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'Auth_user_db'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        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):
        if app_label in self.route_app_labels:
            return db == 'Auth_user_db'
        return None

Конечно... Я включил свои приложения и маршрутизаторы в settings.py следующим образом:

DATABASES = {
    'default': {},
    'Auth_user_db': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'auth_db',
        'HOST': '172.18.0.2',
        'USER': 'root',
        'PASSWORD': 'pass'
    },
    'CTS_ER_BD': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'CTS_ER_BD',
        'HOST': '172.18.0.2',
        'USER': 'root',
        'PASSWORD': 'pass'
    },
    'Polls': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'polls',
        'HOST': '172.18.0.2',
        'USER': 'root',
        'PASSWORD': 'pass'
    }

}

DATABASE_ROUTERS = [
        'routers.Polls_router.PollsRouter',
        'routers.Devices_router.DevicesRouter',
        'routers.Auth_user_router.Auth_userRouter'
    ]

Проблема возникает, когда я пытаюсь выполнить миграции, вот дерево моего проекта до создания файлов миграций:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ tree .
.
├── devices
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── multiple-DB
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── polls
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
└── routers
    ├── Auth_user_router.py
    ├── Devices_router.py
    └── Polls_router.py

4 directories, 23 files

Очевидно, что миграции правильно создаются как:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py makemigrations polls
Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Question
    - Create model Choice
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py makemigrations devices
Migrations for 'devices':
  devices/migrations/0001_initial.py
    - Create model AuthUsers
    - Create model Devices
    - Create model DeviceTypes
    - Create model FirmwareVers
    - Create model HardwareVers
    - Create model Historicals
    - Create model Metadata
    - Create model Projects
    - Create model SoftwareVers
    - Create model Tests
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ tree .
.
├── devices
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       └── __init__.cpython-39.pyc
│   ├── models.py
│   ├── __pycache__
│   │   ├── admin.cpython-39.pyc
│   │   ├── apps.cpython-39.pyc
│   │   ├── __init__.cpython-39.pyc
│   │   ├── models.cpython-39.pyc
│   │   ├── urls.cpython-39.pyc
│   │   └── views.cpython-39.pyc
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── multiple-DB
│   ├── asgi.py
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-39.pyc
│   │   ├── settings.cpython-39.pyc
│   │   └── urls.cpython-39.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── polls
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       ├── 0001_initial.cpython-39.pyc
│   │       └── __init__.cpython-39.pyc
│   ├── models.py
│   ├── __pycache__
│   │   ├── admin.cpython-39.pyc
│   │   ├── apps.cpython-39.pyc
│   │   ├── __init__.cpython-39.pyc
│   │   ├── models.cpython-39.pyc
│   │   ├── urls.cpython-39.pyc
│   │   └── views.cpython-39.pyc
│   ├── tests.py
│   ├── urls.py
│   └── views.py
└── routers
    ├── Auth_user_router.py
    ├── Devices_router.py
    ├── Polls_router.py
    └── __pycache__
        ├── Auth_user_router.cpython-39.pyc
        ├── Devices_router.cpython-39.pyc
        └── Polls_router.cpython-39.pyc

12 directories, 48 files

Проблема в том, что когда я проверяю вывод sqlmigrate для приложения devices, я не могу увидеть правильный SQL скрипт:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py sqlmigrate devices 0001 --database=CTS_ER_BD
--
-- Create model AuthUsers
--
--
-- Create model Devices
--
--
-- Create model DeviceTypes
--
--
-- Create model FirmwareVers
--
--
-- Create model HardwareVers
--
--
-- Create model Historicals
--
--
-- Create model Metadata
--
--
-- Create model Projects
--
--
-- Create model SoftwareVers
--
--
-- Create model Tests
--
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ 

Это приводит к тому, что когда я запускаю python3 manage.py migrate devices --database=CTS_ER_BD для devices:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py migrate devices --database=CTS_ER_BD
Operations to perform:
  Apply all migrations: devices
Running migrations:
  Applying devices.0001_initial... OK

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

Я использую учебник "Написание вашего первого приложения Django" в качестве отправной точки; итак ... Я написал следующие маршрутизаторы базы данных; этот для приложения 'polls':

class PollsRouter:

route_app_labels = {'polls'}

def db_for_read(self, model, **hint):
    if model._meta.app_label == 'polls':
        return 'Polls'
    return None

def db_for_rite(self, model, **hint):
    if model._meta.app_label == 'polls':
        return 'Polls'
    return None

def allow_relation(self, obj1, obj2, **hint):
    if (
        obj1._meta.app_label == 'polls' or
        obj2._meta.app_label == 'polls'
    ):
        return True
    return None

def allow_migrates(self, db, app_label, model_name=None, **hints):
    if app_label == 'polls':
        return db == 'Polls'
    return None

Также класс маршрутизатора для приложения 'devices':

class DevicesRouter:

route_app_labels = {'devices'}

def db_for_read(self, model, **hint):
    if model._meta.app_label == 'devices':
        return 'CTS_ER_BD'
    return None

def db_for_rite(self, model, **hint):
    if model._meta.app_label == 'devices':
        return 'CTS_ER_BD'
    return None

def allow_relation(self, obj1, obj2, **hint):
    if (
        obj1._meta.app_label == 'devices' or
        obj2._meta.app_label == 'devices'
    ):
        return True
    return None

def allow_migrates(self, db, app_label, model_name=None, **hints):
    if app_label == 'devices':
        return db == 'CTS_ER_BD'
    return None

И, наконец, класс маршрутизатора для базы данных 'auth_user' (для нативных приложений Django)

class Auth_userRouter:

    route_app_labels = {'auth', 'contenttypes', 'admin', 'sessions'}

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'Auth_user_db'
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return 'Auth_user_db'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        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):
        if app_label in self.route_app_labels:
            return db == 'Auth_user_db'
        return None

Конечно... Я включил свои приложения и маршрутизаторы в settings.py следующим образом:

DATABASES = {
    'default': {},
    'Auth_user_db': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'auth_db',
        'HOST': '172.18.0.2',
        'USER': 'root',
        'PASSWORD': 'pass'
    },
    'CTS_ER_BD': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'CTS_ER_BD',
        'HOST': '172.18.0.2',
        'USER': 'root',
        'PASSWORD': 'pass'
    },
    'Polls': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'polls',
        'HOST': '172.18.0.2',
        'USER': 'root',
        'PASSWORD': 'pass'
    }

}

DATABASE_ROUTERS = [
        'routers.Polls_router.PollsRouter',
        'routers.Devices_router.DevicesRouter',
        'routers.Auth_user_router.Auth_userRouter'
    ]

Проблема возникает, когда я пытаюсь выполнить миграции, вот дерево моего проекта до создания файлов миграций:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ tree .
.
├── devices
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── multiple-DB
│   ├── asgi.py
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── polls
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   ├── urls.py
│   └── views.py
└── routers
    ├── Auth_user_router.py
    ├── Devices_router.py
    └── Polls_router.py

4 directories, 23 files

Очевидно, что миграции правильно создаются как:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py makemigrations polls
Migrations for 'polls':
  polls/migrations/0001_initial.py
    - Create model Question
    - Create model Choice
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py makemigrations devices
Migrations for 'devices':
  devices/migrations/0001_initial.py
    - Create model AuthUsers
    - Create model Devices
    - Create model DeviceTypes
    - Create model FirmwareVers
    - Create model HardwareVers
    - Create model Historicals
    - Create model Metadata
    - Create model Projects
    - Create model SoftwareVers
    - Create model Tests
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ tree .
.
├── devices
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       └── __init__.cpython-39.pyc
│   ├── models.py
│   ├── __pycache__
│   │   ├── admin.cpython-39.pyc
│   │   ├── apps.cpython-39.pyc
│   │   ├── __init__.cpython-39.pyc
│   │   ├── models.cpython-39.pyc
│   │   ├── urls.cpython-39.pyc
│   │   └── views.cpython-39.pyc
│   ├── tests.py
│   ├── urls.py
│   └── views.py
├── manage.py
├── multiple-DB
│   ├── asgi.py
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-39.pyc
│   │   ├── settings.cpython-39.pyc
│   │   └── urls.cpython-39.pyc
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── polls
│   ├── admin.py
│   ├── apps.py
│   ├── __init__.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   │   └── __pycache__
│   │       ├── 0001_initial.cpython-39.pyc
│   │       └── __init__.cpython-39.pyc
│   ├── models.py
│   ├── __pycache__
│   │   ├── admin.cpython-39.pyc
│   │   ├── apps.cpython-39.pyc
│   │   ├── __init__.cpython-39.pyc
│   │   ├── models.cpython-39.pyc
│   │   ├── urls.cpython-39.pyc
│   │   └── views.cpython-39.pyc
│   ├── tests.py
│   ├── urls.py
│   └── views.py
└── routers
    ├── Auth_user_router.py
    ├── Devices_router.py
    ├── Polls_router.py
    └── __pycache__
        ├── Auth_user_router.cpython-39.pyc
        ├── Devices_router.cpython-39.pyc
        └── Polls_router.cpython-39.pyc

12 directories, 48 files

Проблема в том, что когда я проверяю вывод sqlmigrate для приложения devices, я не могу увидеть правильный SQL скрипт:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py sqlmigrate devices 0001 --database=CTS_ER_BD
--
-- Create model AuthUsers
--
--
-- Create model Devices
--
--
-- Create model DeviceTypes
--
--
-- Create model FirmwareVers
--
--
-- Create model HardwareVers
--
--
-- Create model Historicals
--
--
-- Create model Metadata
--
--
-- Create model Projects
--
--
-- Create model SoftwareVers
--
--
-- Create model Tests
--
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ 

Это приводит к тому, что когда я запускаю python3 manage.py migrate devices --database=CTS_ER_BD для devices:

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py migrate devices --database=CTS_ER_BD
Operations to perform:
  Apply all migrations: devices
Running migrations:
  Applying devices.0001_initial... OK

Таблицы в соответствующей базе данных не создаются:

MySQL [CTS_ER_BD]> SHOW TABLES;
+---------------------+
| Tables_in_CTS_ER_BD |
+---------------------+
| django_migrations   |
+---------------------+

Но, очевидно, миграция для приложения devices сгенерирована правильно! (Я не вставляю его, чтобы не делать этот пост длиннее)

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

Я не уверен, может ли это быть вызвано тем, что оба файла миграции называются одинаково (0001_initial.py), должен ли я выбирать разные для каждого приложения? В любом случае ... оба находятся в разных папках, так что я не вижу в этом никакой проблемы.

Миграции для опросов и нативных приложений Django работают правильно (очевидно), фактически для приложения 'polls' вы можете увидеть правильный вывод для sqlmigrate

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py sqlmigrate polls 0001 --database=Polls
--
-- Create model Question
--
CREATE TABLE `polls_question` (`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `question_text` varchar(200) NOT NULL, `pub_date` datetime(6) NOT NULL);
--
-- Create model Choice
--
CREATE TABLE `polls_choice` (`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `choice_text` varchar(200) NOT NULL, `votes` integer NOT NULL, `question_id` bigint NOT NULL);
ALTER TABLE `polls_choice` ADD CONSTRAINT `polls_choice_question_id_c5b4b260_fk_polls_question_id` FOREIGN KEY (`question_id`) REFERENCES `polls_question` (`id`);
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$

Так что я не уверен, что делаю неправильно. Если вы хотите посмотреть проект ... Я отслеживаю его в GitLab https://gitlab.com/ralbarran1/multiple-db-in-django

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

соответствующие базы данных не создаются:

MySQL [CTS_ER_BD]> SHOW TABLES;
+---------------------+
| Tables_in_CTS_ER_BD |
+---------------------+
| django_migrations   |
+---------------------+

Но, очевидно, миграция для приложения devices сгенерирована правильно!:

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

Я не уверен, может ли это быть вызвано тем, что оба файла миграции называются одинаково (0001_initial.py), должен ли я выбирать разные для каждого приложения? В любом случае ... оба находятся в разных папках, так что я не вижу в этом никакой проблемы.

Миграции для опросов и нативных приложений Django работают правильно (очевидно), фактически для приложения 'polls' вы можете увидеть правильный вывод для sqlmigrate

(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ python3 manage.py sqlmigrate polls 0001 --database=Polls
--
-- Create model Question
--
CREATE TABLE `polls_question` (`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `question_text` varchar(200) NOT NULL, `pub_date` datetime(6) NOT NULL);
--
-- Create model Choice
--
CREATE TABLE `polls_choice` (`id` bigint AUTO_INCREMENT NOT NULL PRIMARY KEY, `choice_text` varchar(200) NOT NULL, `votes` integer NOT NULL, `question_id` bigint NOT NULL);
ALTER TABLE `polls_choice` ADD CONSTRAINT `polls_choice_question_id_c5b4b260_fk_polls_question_id` FOREIGN KEY (`question_id`) REFERENCES `polls_question` (`id`);
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$

Так что я не уверен, что делаю неправильно. Если вы хотите посмотреть проект ... Я отслеживаю его в GitLab https://gitlab.com/ralbarran1/multiple-db-in-django

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

На самом деле проблема была в модели:

class DeviceTypes(models.Model):
    device_name = models.CharField(max_length=50)
    client_ref = models.CharField(max_length=100)
    colway_ref = models.CharField(max_length=100)
    power_dis = models.IntegerField(blank=True, null=True)

    def __str__(self):
        return f'{self.colway_ref}', {self.device_name}

    class Meta:
        managed = Fase
        db_table = 'device_types'

Это META OPTIONS managed = False мешало Django управлять этой моделью.

Это произошло потому, что я позволил Django генерировать модель из SQL скрипта с помощью python manage.py inspectdb > models.py и это устанавливает по умолчанию managed = False

Вернуться на верх