Django - how to specify a database for a model?

前端 未结 6 1410
滥情空心
滥情空心 2020-11-29 04:53

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.

6条回答
  •  不知归路
    2020-11-29 05:39

    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
    

提交回复
热议问题