2

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

Jøê Grèéñ
  • 551
  • 1
  • 6
  • 15

1 Answers1

7

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.

Withnail
  • 3,128
  • 2
  • 30
  • 47
  • Thanks for the help!!! But can you explain me more about the Database Routers topic – Jøê Grèéñ Feb 08 '17 at 13:52
  • What do you need explained? A workable example is literally in the answer and in the docs. 'Can you explain more' [is a poor question](http://stackoverflow.com/help/how-to-ask) - what specifically do you need? Also, if the docs on this aren't clear for you, then I really recommend not pursuing this approach! – Withnail Feb 08 '17 at 13:54
  • The Database Routers concept. Can you explain on it?? Like where should it stay?? Are routers specific for apps or for databases??? Where should I keep my routers and some working examples maybe – Jøê Grèéñ Feb 08 '17 at 13:58
  • I'd probably put it in a `routers.py` file and import that into your settings. The examples above are pretty clear that a DB router is driven by the `app_label`. Read through the docs I linked and give it a go. – Withnail Feb 08 '17 at 14:13