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
- Suppose you need to record all the touchpoints of a web page in your web application, for this you need a non-relation database to store that data to run some analytical result on it.
- Read replicas, you need to set up read replicas of your default database to speed up the fetching of data from the database.
- Saving the email metadata like how many emails were sent, open rate, error rate, link clicked to see the engagement of the emails.
Lets us see how to set up multiple databases in the Django project.
- 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']
- 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!