3

In Django when using multiple DB's how to map databases, for ex: from request there is a parameter as app1 which maps to db1 and another request app2 mapping to db2. Now how to choose db's much before sending the request to views

DATABASE_APPS_MAPPING = {'app1':'db1','app2':'db2'}


DATABASES = {
  'default': {
  },
  'db1': {
      'ENGINE': 'django.db.backends.mysql',
      'NAME': 'hp1',
      'USER': 'server',
      'PASSWORD': 'hpdata',
      'HOST': '192.168.3.11',
      'PORT': '3306'
  },
  'db2': {
      'ENGINE': 'django.db.backends.mysql',
      'NAME': 'hp2',
      'USER': 'server',
      'PASSWORD': 'hpdata',
      'HOST': '192.168.3.11',
      'PORT': '3306'
  }
}
Rajeev
  • 44,985
  • 76
  • 186
  • 285

2 Answers2

3

Let's say I can import a function that gives me the database:

project/app/views.py:

from .utils import which_db, item_search
from django.shortcuts import render
from .models import SomeModel

def some_view(request):
    obj = SomeModel.objects.using(which_db(request)).filter(**item_search(request))
    return render(request, "some_model.html", {'object':obj}

It's a bother having to append the using every time. There is a way to route similar queries to different databases (documented here in more detail).

project/settings.py:

DATABASE_ROUTERS = ['project.db_routes.AppRouter',]
DB_ROUTING = {'app1':'db1','app2':'db2'}

project/db_routes.py:

from django.conf import settings


class AppRouter:
    def __init__(self):
        self.DB = settings.DB_ROUTING

    def db_for_read(self, model, **hints):
        return self.DB.get(self.model.app_label, 'default')

    def db_for_write(self, model, **hints):
        return self.DB.get(self.model.app_label, 'default')

    def allow_relation(self, obj1, obj2, **hints):
        return True

    def allow_migrate(self, db, app_label, model=None, **hints):
        return self.DB.get(app_label, None)

I'm assuming you want to be able to have foreignkeys between the databases. If not, return False from allow_relation. allow_migrate insures objects only exists in their proper database.

I have not tested this solution, but it does conform to the documentation.

  • It's not clear what you are asking. I see you are trying your best. So am I. What you seem to want to do is either write a Manager which sets the proper using clause (but the Manager doesn't have access to the request). There are no middleware hooks to process SQL queries. Your use case may lend itself to database routing. – Árni St. Steinunnarson Oct 07 '15 at 11:38
  • My question is very simple ,from my request i would know whether i have to use app1 or app2 .so when i know i have to use app2 what should be done in middleware to set the connections for app2 instead of setting it in views like SomeModel.objects.using(which_db(request)).filter() in the views – Rajeev Oct 07 '15 at 12:24
  • There is no middleware for this. Try the routing solution. I think it does what you want. – Árni St. Steinunnarson Oct 07 '15 at 12:25
  • If you want more complicated rules then you need to write that discriminant in the AppRouter class. If you simply want reads to go to your read-only slave and writes to master, then you only need to return the identifying string in each function. – Árni St. Steinunnarson Oct 07 '15 at 12:29
0

I'm not entirely sure what you want to do. But my guess is that you'll find your answer here:

https://docs.djangoproject.com/en/1.8/topics/db/multi-db/#topics-db-multi-db-routing

If you really want to select a database based on the url (subdomain e.a.) than you will have to write a custom Middleware class:

https://docs.djangoproject.com/en/1.8/topics/http/middleware/

user1797792
  • 1,169
  • 10
  • 26
  • even if there is a custom middle ware how to select the database with app1 or app2 any examples.. – Rajeev Oct 07 '15 at 08:25