set db per model in django

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']

Source


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


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.

Tags:

Python

Django