Django: Connecting multiple databases.

Django provides the support of using multiple databases in your project. Let's see how we can do that, but first, let me put some use case where we might need multiple databases for our application. Why need multiple databases? In today's world, we are gathering a lot of data from user which is used for different purposes, some data is relational data and other is non-relational data. Let me put few use cases

Lets us see how to set up multiple databases in the Django project.

  1. Need to add the details of the databases in settings.py of Django project.
DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": config.get("database_default", "name"),
        "USER": config.get("database_default", "user"),
        "PASSWORD": config.get("database_default", "password"),
        "HOST": config.get("database_default", "host"),
        "PORT": "3306",
        "CONN_MAX_AGE": 0,
    },
    "replica1": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": config.get("database_replica1", "name"),
        "USER": config.get("database_replica1", "user"),
        "PASSWORD": config.get("database_replica1", "password"),
        "HOST": config.get("database_replica1", "host"),
        "PORT": "3306",
        "CONN_MAX_AGE": 0,
    },
    "mongo": {
        "ENGINE": "djongo",
        "NAME": config.get("mongo_database", "name"),
        "HOST": config.get("mongo_database", "host"),
        "USER": config.get("mongo_database", "user"),
        "PASSWORD": config.get("mongo_database", "password"),
    },
}

Here you can see we define 2 databases other than the default databases mongo and replica1. After this, you need to tell the Django router in which app you want to use which connection of database. This is one of the ways to do it, you can manually decide which database you want to use while querying.

DATABASE_ROUTERS = ['path.to.replica1', 'path.to.mongo']
  1. Now we need to define this router class to tell them which database to use, for that we need to write a class
class MongoRouter:
    """
    A router to control all database operations on models in the
    analytics and status applications.
    """
    route_app_labels = {'analytics', 'status'}

    def db_for_read(self, model, **hints):
        """
        Attempts to read analytics and status models go to mongo db.
        """
        if model._meta.app_label in self.route_app_labels:
            return 'mongo'
        return None

    def db_for_write(self, model, **hints):
        """
        Attempts to write analytics and status models go to auth_db.
        """
        if model._meta.app_label in self.route_app_labels:
            return 'mongo'
        return None

    def allow_relation(self, obj1, obj2, **hints):
        """
        Allow relations if a model in the analytics and status apps is
        involved.
        """
        if (
            obj1._meta.app_label in self.route_app_labels or
            obj2._meta.app_label in self.route_app_labels
        ):
           return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Make sure the analytics and status apps only appear in the
        'mongo' database.
        """
        if app_label in self.route_app_labels:
            return db == 'mongo
        return None

similar goes for replica1 database


class ReplicaRouter:
    def db_for_read(self, model, **hints):
        """
        Reads go to replica1.
        """
        return 'replica1'

    def db_for_write(self, model, **hints):
        """
        Writes always go to default.
        """
        return 'default'

    def allow_relation(self, obj1, obj2, **hints):
        """
        Relations between objects are allowed if both objects are
        in the default/replica1 pool.
        """
        db_set = {'default', 'replica1'}
        if obj1._state.db in db_set and obj2._state.db in db_set:
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        All non-mongo models end up in this pool.
        """
        return True

That's it, now you read to use multiples database in your project, which we early handle by the routers class you have defined.

Cheers!

#100DaysToOffload #Django #Python