I would like to create a new table in a specific Postgresql schema (i.e. "schema1) from a Django migration.
Despite following approach 1 from this blog or this post, the migration sends the table to the default schema "public" instead of "schema1".
In settings.py
, I have:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'OPTIONS': {
'options': '-c search_path=django,public'
},
'NAME': 'myDB',
'USER': 'username',
'PASSWORD': '***',
'HOST': 'my.host.address',
'PORT': '1234',
},
'schema1': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'OPTIONS': {
'options': '-c search_path=schema1,public'
},
'NAME': 'myDB',
'USER': 'username',
'PASSWORD': '***',
'HOST': 'my.host.address',
'PORT': '1234',
}
}
#Path to DBrouter to handle PG schemas https://stackoverflow.com/a/51007441/3976696
DATABASE_ROUTERS = ('djangogirls.dbrouters.MyDBRouter',)
In djangogirls/dbrouters.py
, I have:
from legacydbapp.models import MyUser
# Include here any class (i.e. table) that belongs to the schema "schema1"
ROUTED_MODELS_SCHEMA1 = [MyUser]
class MyDBRouter(object):
"""
A router to place DB queries into correct schema depending on considered tables.
"""
def db_for_read(self, model, **hints):
if model in ROUTED_MODELS_SCHEMA1 :
return 'schema1'
return None
def db_for_write(self, model, **hints):
if model in ROUTED_MODELS_SCHEMA1 :
return 'schema1'
return None
And the model class I'm trying to migrate, in models.py
:
class MyUser(models.Model):
first_name = models.CharField(max_length=30, default='',null=True, blank=True)
last_name = models.CharField(max_length=30, default='', null=True, blank=True)
profession = models.CharField(max_length=32,default='', null=True, blank=True)
def __str__(self):
return self.first_name + " " + self.last_name
class Meta:
managed = True
db_table = 'myuser'
I ran the following commands:
$ python manage.py makemigrations legacydbapp
$ python manage.py sqlmigrate legacydbapp 0001_initial
$ python manage.py migrate legacydbapp
And the sqlmigrate returns the following SQL:
BEGIN;
--
-- Create model MyUser
--
CREATE TABLE "myuser" (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NULL,
"last_name" varchar(30) NULL,
"profession" varchar(32) NULL);
COMMIT;
If the DB router were working, I would expect the SQL to read instead CREATE TABLE "schema1.myuser"
, but this isn't the case. Did I mess up somewhere, or is this simply not achievable in Django 2.1.5?
You have to explicitly provide the name of the database definition when running migrate:
$ python manage.py migrate legacydbapp --database schema1
To ensure that the model MyUser
is only created in a specific database, your router has to implement .allow_migrate()