I've the databases db1
and db2
. The schemas of both DBs should be created with the same migration script.
The Django docs mention DATABASE_ROUTERS and RunPython, but I didn't manage to get it working so far. The function is called, but migrations.CreateModel()
has no impact when called from the function: the table is not created.
Migration script:
# 0001_initial.py
def forwards(apps, schema_editor):
if schema_editor.connection.alias == 'db1':
print('This line is called!')
migrations.CreateModel(
name='MyModel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
# ...
]
)
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.RunPython(forwards, hints={'target_db': 'db1'}),
]
Router:
DatabaseRouter:
# ...
def allow_migrate(self, db, app_label, model_name=None, **hints):
if 'target_db' in hints:
return db == hints['target_db']
return True
Command:
python manage.py migrate --database=db1
Any idea? Thanks in advance!
migrations.CreateModel
does not create a model in the database upon instantiation. It is supposed to be present in the operations
list where the migrations system will then use it to create the model. Furthermore you shouldn't be writing this migration manually anyway! Just write the code for the model in models.py
:
class MyModel(models.Model):
# Your fields, etc.
Next since your question asks how to control which model is migrated to which database. These tasks are supposed to be done in the Database router, particularly in the allow_migrate
method. You can check the values passed for db
, app_label
, and model_name
return whether the model should be migrated there. For example:
class MyRouter:
def db_for_read(self, model, **hints):
...
def db_for_write(self, model, **hints):
...
def allow_relation(self, obj1, obj2, **hints):
...
def allow_migrate(self, db, app_label, model_name=None, **hints):
# Suppose I want to migrate all models from the app 'some_app' to 'db1' only.
if app_label in ['some_app']:
return db == 'db1'
# Suppose I want to migrate 'MyModel' to 'db2' only.
if model_name == 'mymodel': # 'mymodel' is lowercase 'MyModel'
return db == 'db2'
return None