DEV Community

Vuyisile Ndlovu
Vuyisile Ndlovu

Posted on • Originally published at vuyisile.com on

How to use Django with multiple databases

There may come a time in the life of your Django project where you need to use multiple databases. Django provides two ways of doing this and in this article, I will show you how.

Let Django know about your Database

For Django to know about your database(s), you must add them to the database dictionary in your project’s settings.py file. This looks like this:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE\_DIR, 'db.sqlite3'),
    },
    'customers\_db': {
        'NAME': 'customers',
        'ENGINE': 'django.db.backends.postgresql',
        'USER': 'postgres\_user',
        'PASSWORD': 'root'
    }
}
Enter fullscreen mode Exit fullscreen mode

Adding the database to settings.py is the first step. Django will by default associate any models and queries you create with the default database. In the above configuration, the default database is the sqlite database labelled as such. To associate queries or models with a different database, you can either:

  1. Explicitly state which database to use when making a query or saving to the database or
  2. Set up a database routing scheme that will automatically select the right database for you.

Specifying the database to use when making queries.

For the purposes of this post, let’s assume these are your models:

# models.py

class Customer(models.Model):
    name = models.CharField(max_length=20)
    customer_id = models.CharField(max_length=120)

class User(models.Model):
    name = models.CharField(max_length=20)
    user_id = models.CharField(max_length=120)
    age = models.IntegerField()
Enter fullscreen mode Exit fullscreen mode

To manually select the database you want in your query use theusing() method. using() takes a database alias as its argument. Here is an example:


>>> default_user = User(name='Sipho', user_id='12:3456', age=57)
>>> default_user.save() # user object saved to default database
>>> customer = Customer(name='Thandiwe Ndiweni', customer_id='86:19216857') 

# Saving to different database

>>> customer.save(using='customers_db')
>>> Customer.objects.all().using('customers_db')

Enter fullscreen mode Exit fullscreen mode

Here, you see that customer is created and retrieved from the customers database by specifying the database name as an argument to using.

If you to write a lot of similar queries, it is a good idea to write a database router to automatically handle database selections. A database router is like a urlconfig but for databases. Here is an example of a router you could write to handle database operations for the customers database:

class YourRouter:
    """
 A router to control all database operations on models in the
 customer application.
 """
    def db\_for\_read(self, model, \*\*hints):
        """
 Attempts to read user models go to customers\_db.
 """
        if model.\_meta.app\_label == 'user\_data':
            return 'customers\_db'
        return None

    def db\_for\_write(self, model, \*\*hints):
        """
 Attempts to write user models go to users\_db.
 """
        if model.\_meta.app\_label == 'customer\_data':
            return 'customers\_db'
        return None

    def allow\_relation(self, obj1, obj2, \*\*hints):
        """
 Allow relations if a model in the user app is involved.
 """
        if obj1.\_meta.app\_label == 'customer\_data' or \
           obj2.\_meta.app\_label == 'customer\_data':
           return True
        return None

    def allow\_migrate(self, db, app\_label, model\_name=None, \*\*hints):
        """
 Make sure the auth app only appears in the 'customers\_db'
 database.
 """
        if app\_label == 'customer\_data':
            return db == 'customers\_db'
        return None
Enter fullscreen mode Exit fullscreen mode

Place the code above in a module in an appropriate location in your app and then point Django to it by adding this line to settings.py :

DATABASE\_ROUTERS = ['path.to.YourRouter']
Enter fullscreen mode Exit fullscreen mode

substituting path.to with the actual Python module where you defined the router. Next, modify the models and give them app_labels:

# models.py

class Customer(models.Model):
    name = models.CharField(max_length=20)
    customer_id = models.CharField(max_length=120)

    class Meta:
        app_label = 'customer_data'

class User(models.Model):
    name = models.CharField(max_length=20)
    user_id = models.CharField(max_length=120)
    age = models.IntegerField()

    class Meta:
        app_label = 'user_data'
Enter fullscreen mode Exit fullscreen mode

Synchronising your databases.

migrate works on the default database by default, so to synchronize changes to other databases, pass them as options to the command:

./manage.py migrate --database=customers_db
Enter fullscreen mode Exit fullscreen mode

Conclusion

This post gave you an overview of working with multiple databases in Django. You saw how to add more than one database to the configuration, how to manually select a database to be targeted by a query or save operation and how to create custom database routers. The official docs cover more detail about how to perform additional operations such as deleting records, or moving records between databases. Thanks for reading.

References:

  1. Django Docs
  2. Django ORM CookBook

Top comments (0)