Reputation: 11
I'm trying to make a multiple database project in Django. But I'm having problems to properly migrate my models to the appropriate database.
I'm using the 'Writing your first Django app' tutorial as a starting point; so ... I've written the following database routers; this one for 'polls' app:
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
Also the router class for 'devices' app:
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
And finally, the router class for 'auth_user' database (for native Django apps)
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
Of course ... I've included my apps and routers in the settings.py as this:
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'
]
The problem comes when I try to perform the migrations, this is the tree of my project before creating migrations files:
(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
Apparently migrations are properly created as:
(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
The problem is that when I check the sqlmigrate
output for devices
app I can't see a proper SQL script:
(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$
This is causing that when I run python3 manage.py migrate devices --database=CTS_ER_BD
for 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
Tables in thi guys, I'm trying to make a multiple database project in Django. But I'm having problems to properly migrate my models to the appropriate database.
I'm using the 'Writing your first Django app' tutorial as a starting point; so ... I've written the following database routers; this one for 'polls' app:
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
Also the router class for 'devices' app:
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
And finally, the router class for 'auth_user' database (for native Django apps)
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
Of course ... I've included my apps and routers in the settings.py as this:
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'
]
The problem comes when I try to perform the migrations, this is the tree of my project before creating migrations files:
(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
Apparently migrations are properly created as:
(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
The problem is that when I check the sqlmigrate
output for devices
app I can't see a proper SQL script:
(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$
This is causing that when I run python3 manage.py migrate devices --database=CTS_ER_BD
for 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
Tables in the corresponding database aren't being created:
MySQL [CTS_ER_BD]> SHOW TABLES;
+---------------------+
| Tables_in_CTS_ER_BD |
+---------------------+
| django_migrations |
+---------------------+
But apparently the migration for devices
app is properly generated! (I'm not pasting it to don't make this post longer)
So I don't understand why sqlmigrate
is not showing a proper sql script. Or the migration isn't properly performed.
I'm not sure if this may be caused by the fact both migration files are actually called in the same way (0001_initial.py
), should I choose a different one for each app? Anyway ... both are in different folders, so I don't see any problem with this.
Migrations for polls and Django native apps are properly working (apparently), in fact for 'polls' app you can see a proper output for 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$
So I'm not sure what I'm doing wrong. If you want to see the project ... I'm tracking it in GitLab https://gitlab.com/ralbarran1/multiple-db-in-django
Thank you very much, I'm sorry if the question is too long or if it's duplicated, I can see several similar questions, but too old I think.
he corresponding database aren't being created:
MySQL [CTS_ER_BD]> SHOW TABLES;
+---------------------+
| Tables_in_CTS_ER_BD |
+---------------------+
| django_migrations |
+---------------------+
But apparently the migration for devices
app is properly generated!:
(venv) raul@raul:~/multiple-db-in-django/multiple-DB$ cat devices/migrations/0001_initial.py
# Generated by Django 4.0.4 on 2022-04-29 09:39
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='AuthUsers',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('user_name', models.CharField(max_length=50)),
],
options={
'db_table': 'auth_users',
'managed': False,
},
),
migrations.CreateModel(
name='Devices',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('serial_number', models.IntegerField()),
('manufacture_date', models.DateTimeField(blank=True, null=True)),
('devices_tag', models.ImageField(blank=True, null=True, upload_to='')),
],
options={
'db_table': 'devices',
'managed': False,
},
),
migrations.CreateModel(
name='DeviceTypes',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('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)),
],
options={
'db_table': 'device_types',
'managed': False,
},
),
migrations.CreateModel(
name='FirmwareVers',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('firmware_name', models.CharField(blank=True, max_length=50, null=True)),
('manuf_type', models.CharField(blank=True, max_length=50, null=True)),
],
options={
'db_table': 'firmware_vers',
'managed': False,
},
),
migrations.CreateModel(
name='HardwareVers',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('hw_type', models.CharField(blank=True, db_column='HW_type', max_length=1, null=True)),
],
options={
'db_table': 'hardware_vers',
'managed': False,
},
),
migrations.CreateModel(
name='Historicals',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('test_date', models.DateTimeField(blank=True, null=True)),
('reuslt', models.BooleanField(blank=True, null=True)),
],
options={
'db_table': 'historicals',
'managed': False,
},
),
migrations.CreateModel(
name='Metadata',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
],
options={
'db_table': 'metadata',
'managed': False,
},
),
migrations.CreateModel(
name='Projects',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('project_name', models.CharField(blank=True, max_length=50, null=True)),
],
options={
'db_table': 'projects',
'managed': False,
},
),
migrations.CreateModel(
name='SoftwareVers',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('colway_ref', models.CharField(blank=True, max_length=100, null=True)),
('joifi_ref', models.CharField(blank=True, max_length=100, null=True)),
],
options={
'db_table': 'software_vers',
'managed': False,
},
),
migrations.CreateModel(
name='Tests',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('test_name', models.CharField(blank=True, max_length=50, null=True)),
('prefix', models.CharField(blank=True, max_length=1, null=True)),
],
options={
'db_table': 'tests',
'managed': False,
},
),
]
So I don't understand why sqlmigrate
is not showing a proper sql script. Or the migration isn't properly performed.
I'm not sure if this may be caused by the fact both migration files are actually called in the same way (0001_initial.py
), should I choose a different one for each app? Anyway ... both are in different folders, so I don't see any problem with this.
Migrations for polls and Django native apps are properly working (apparently), in fact for 'polls' app you can see a proper output for 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$
So I'm not sure what I'm doing wrong. If you want to see the project ... I'm tracking it in GitLab https://gitlab.com/ralbarran1/multiple-db-in-django
Thank you very much, I'm sorry if the question is too long or if it's duplicated, I can see several similar questions, but too old I think.
Upvotes: 0
Views: 857
Reputation: 11
The problem actually was in the model:
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'
This META OPTIONS managed = False
was preventing Django from managing this model.
This was because I let Django to generate the model from an SQL script with python manage.py inspectdb > models.py
and this sets by default managed = False
Upvotes: 1