[Fixed]-Set db per model in django


There is no Meta field for this (there was one at some point but it got removed because of the limitations it introduced). You need a database router to control which objects go to what database. In your case the router should be pretty easy to implement.


You can easily do this by appearing custom attribute to model:

class A(models.Model):
    _DATABASE = "X"

class B(models.Model):
    _DATABASE = "Y"

Then you need to add router. Next one will select database by _DATABASE field, and models without _DATABASE attribute will use default database, also relationships will be allowed only for default database:

class CustomRouter(object):

    def db_for_read(self, model, **hints):
        return getattr(model, "_DATABASE", "default")
    def db_for_write(self, model, **hints):
        return getattr(model, "_DATABASE", "default")

    def allow_relation(self, obj1, obj2, **hints):
        Relations between objects are allowed if both objects are
        in the master/slave pool.
        db_list = ('default')
        return obj1._state.db in db_list and obj2._state.db in db_list

    def allow_migrate(self, db, model):
        All non-auth models end up in this pool.
        return True  

And the last step is specifing your router in settings.py:

DATABASE_ROUTERS = ['path.to.class.CustomRouter']


BTW this solution will not work if you are going to work with many-to-many relations in non-default database because relational models will not have "_DATABASE", attribute, in this case, better to use something like model._meta.app_label as filter condition in db_for_read/db_for_write

Leave a comment