Is there a way to specify that a model (or app, even) should only ever use one particular database?
I am working with a legacy database that I don\'t want to change.
Building on Mark's excellent answer - here's how to route both model read/write operations and migrations to different databases based on an attribute of the model
# app/models.py
class SomeModel(models.Model):
class params:
db = 'default'
class SomeOtherDbModel(models.Model):
class params:
db = 'otherdb'
...
# app/dbrouters.py
import app.models
allmodels = dict([(name.lower(), cls) for name, cls in app.models.__dict__.items() if isinstance(cls, type)])
...
class MyDBRouter(object):
def db_for_read(self, model, **hints):
""" reading model based on params """
return getattr(model.params, 'db')
def db_for_write(self, model, **hints):
""" writing model based on params """
return getattr(model.params, 'db')
def allow_migrate(self, db, app_label, model_name = None, **hints):
""" migrate to appropriate database per model """
model = allmodels.get(model_name)
return(model.params.db == db)
# app/settings.py
DATABASE_ROUTERS = ('app.dbrouters.MyDBRouter',)
...
DATABASES = {
...
'otherdb': {
....
}
}
See docs here: https://docs.djangoproject.com/en/3.0/topics/db/multi-db/#database-routers
The model_name argument is passed at runtime as the lower case of the model.__name__, hence why we built the lookup dictionary by casting this attribute to lower.
Migrations should then be run as
python3 manage.py migrate app --database default
python3 manage.py migrate app --database otherdb