Django - how to specify a database for a model?

I found that you can route models pretty simply with this manager:

class SecondDbManager(models.Manager):
    def get_queryset(self):
        qs = super().get_queryset()

        # if `use_db` is set on model use that for choosing the DB
        if hasattr(self.model, 'use_db'):
            qs = qs.using(self.model.use_db)

        return qs

Just add use_db='databasename' and this manager to your model and it works.

Or to further simplify it I created a base model for it:

class SecondDbBase(models.Model):
    use_db = 'my_second_db'
    objects = SecondDbManager()

    class Meta:
        abstract = True

And with this all you need to do is extend it like so. Instead of:

class Customer(models.Model):

Just do this and it works:

class Customer(SecondDbBase):

PS. I'm not sure if it's a good practice or the best solution but it works and routing to other databases is a breeze :)

PPS. I've only ever used these for only reading and writing tables that are not managed by Django(managed = False) so if you need to create migrations for them, I'm not sure if it works or not. Might still need to use DATABASE_ROUTERS for that.


You can't specify a database for a model, but you can define it in a custom DB router class.

# app/models.py
class SomeModel(models.Model):
    ...

# app/dbrouters.py
from app.models import SomeModel
...
class MyDBRouter(object):

    def db_for_read(self, model, **hints):
        """ reading SomeModel from otherdb """
        if model == SomeModel:
            return 'otherdb'
        return None

    def db_for_write(self, model, **hints):
        """ writing SomeModel to otherdb """
        if model == SomeModel:
            return 'otherdb'
        return None


# app/settings.py
DATABASE_ROUTERS = ('app.dbrouters.MyDBRouter',)
...
DATABASES = {
    ...
    'otherdb': {
        ....
    }
}

The simple solution is to set the manager to always use a specific database for the model. Look into Django's using.

Example:

class User(models.Model):
    birth_date = models.DateField()

    class Meta:
        managed = False
        db_table = 'myotherapp_user'

User.objects = User.objects.using('myotherdb')

Then you can use User.objects and it will always use the 'myotherdb' database instead of 'default'.

Note that relations between models from different databases will not work, but this is an issue with Django since it does not support this out of the box.


As far as I know you can't specify the database directly with the model since it would kind of prevent the app from ever being reusable, but from what I can see in the docs:

https://docs.djangoproject.com/en/1.8/topics/db/multi-db/