Multiple database implementation in Django

New with Django 1.2 came multiple database support.

It just so happened that I am putting together such a project and had need of this feature. It was one of those tasks which seemed dauntingly complicated at first, though when I got it working, seemed surprisingly easy. However, the documentation, of which the official docs are the best offering, left me scratching my head for some time. So in this post I aim to lay things out a little more clearly for someone who is attempting this for the first time, and of course as a reference for myself.

My use case may or may not be typical but I would bet it is not rare. I had two independent Django projects which had an app each. The time came when these needed to be two apps in a larger project, but they still required discrete databases. So I rolled one into the other and dealt with my need for multi-db support by using the manual method.

This definitely worked but was more of a stop-gap until I worked up courage to tackle the automatic routing method. My primary motivation was that I needed to have access to both apps in the admin, which required the automatic method. Aside from that, the frequency of the using method such as:

item = Item.objects.using('my_db_2').all() 

was getting ugly and daunting to keep track of.

So when it came to it, implementing automatic routing came down to three main steps:

  1. Define database connections in myproject/settings.py:
    DATABASES = {
        'default': {
            'NAME': 	'db1',
            'ENGINE': 	'django.db.backends.mysql',
            'USER': 	'myuser1',
            'PASSWORD':    'mypass1',
        },
        'my_db_2': {
            'NAME': 	'db2',
            'ENGINE': 	'django.db.backends.mysql',
            'USER': 	'myuser2',
            'PASSWORD':    'mypass2'
        }
    }
  2. Define router in myproject/myapp2/router.py:
    class MyApp2Router(object):
        """
        A router to control all database operations on models in
        the myapp2 application
        """
    
        def db_for_read(self, model, **hints):
            """
            Point all operations on myapp2 models to 'my_db_2'
            """
            if model._meta.app_label == 'myapp2':
                return 'my_db_2'
            return None
    
        def db_for_write(self, model, **hints):
            """
            Point all operations on myapp models to 'other'
            """
            if model._meta.app_label == 'myapp2':
                return 'my_db_2'
            return None
    
        def allow_syncdb(self, db, model):
            """
            Make sure the 'myapp2' app only appears on the 'other' db
            """
            if db == 'my_db_2':
                return model._meta.app_label == 'myapp2'
            elif model._meta.app_label == 'myapp2':
                return False
            return None
    

    This is pretty much a copy and paste job from the official example. The one key point left out was where to define this. It turns out that myapp2/models.py is not the right place and something like myapp2/router.py is!

  3. Now all that remains is to tell our project about the router. In myproject/settings.py add:
    DATABASE_ROUTERS = ['myapp.routers.MyApp2Router',]
    

You can see that throughout I am only concerned with my second app (myapp2). This is because, for the time being myapp1 would use the default database router which comes out of the box with Django. Of course at some point I may well need another router for that app or an additional one, which is when I could define I new router, hook it up to said app and add the router path to the settings.

I am sure that there are a number of unexplored nuances to working with multiple databases in Django, and I admit I have not delved into the underlying code of this functionality, but for the time being everything seems to works as required. The really impressive part was seeing both apps in the admin without errors.

Thanks Django.

About these ads

5 thoughts on “Multiple database implementation in Django

  1. Pingback: Multiple Database Routing App Label OffCopyQuery CopyQuery | Question & Answer Tool for your Technical Queries,CopyQuery, ejjuit, query, copyquery, copyquery.com, android doubt, ios question, sql query, sqlite query, nodejsquery, dns query, update que

  2. @nofb_@hotmail.com: I have updated the post to reflect your comments. In hindsight, copy/pasting from the Django docs should have involved a little more scrutiny. It is true that the allow_relation is unnecessary if the database do not contain any FK relationships across dbs. The allow_syncdb is needed however, to keep the tables in the correct dbs. For instance if this is removed from one app, Django will start including the auth and session tables when you run syncdb. These are only required in the default db.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s