Search code examples
djangopython-3.xdjango-database

Multiple Database in Django


I am trying to create a Q/A website using Django and I want to use mutiple databases for all the apps

  • Two secure database like admin, auth, forum
  • A less secure (like sqlite3) database for the rest

But I don't want to re-configure my models and apps.

How can I do that??

N.B: forum is the app that implements the Q/A website


Solution

  • I mean, you're obviously going to have to do some reconfiguration.

    Broadly, set up the most commonly used database as default, and your other one as something else - this is adapted from one of my db listings from an in production site.

    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.mysql',
            'NAME': 'databasename',
            'USER': 'mydefaultuser',
            'PASSWORD': 'novelpassword',
            'HOST':'first-host.com',
            'PORT':'3306'
        },
        'auth': {
            'ENGINE': 'sqlserver_pymssql',
            'HOST': 'myserver.com',
            'NAME': 'myauthdatabase',
            'PASSWORD': 'passwordhere',
            'PORT': 1433,
            'USER': 'username'
        }}
    

    Then you can either use th eother database explicitly in your views, using using: User.objects.using('auth').all()

    ...or preferably, you can set it more widely using a Database Router:

    class AuthRouter(object):
        """
        A router to control all database operations on models in the
        auth application.
        """
        def db_for_read(self, model, **hints):
            """
            Attempts to read auth models go to auth_db.
            """
            if model._meta.app_label == 'auth':
                return 'auth_db'
            return None
    
        def db_for_write(self, model, **hints):
            """
            Attempts to write auth models go to auth_db.
            """
            if model._meta.app_label == 'auth':
                return 'auth_db'
            return None
    
        def allow_relation(self, obj1, obj2, **hints):
            """
            Allow relations if a model in the auth app is involved.
            """
            if obj1._meta.app_label == 'auth' or \
               obj2._meta.app_label == 'auth':
               return True
            return None
    
        def allow_migrate(self, db, app_label, model_name=None, **hints):
            """
            Make sure the auth app only appears in the 'auth_db'
            database.
            """
            if app_label == 'auth':
                return db == 'auth_db'
            return None
    

    Adding DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.PrimaryReplicaRouter'] in your settings file - these are just examples drawn from the docs at the links above, but it's relatively straightforward.

    I would say, that unless you have a super clear and concise reason why you want to do this, don't do it. You can handle all of this in a single database, and as soon as you go the multiple database route, you have the cross-database limitations straight away - always worth bearing in mind.