Multi database and Multi sites Django

1

I try to make an API Rest Application in Django and I try to make several domains (example1.com, example2.com, example3.com) at the time of making requests are directed with the database of each one.

Each domain has its database in postgresql.

Django allows to use Multi Databases and to be able to use that strategy there are 2 ways:

1.- At the moment of making a query in the ORM

 Articulos.object.using('database1').get(id=id) #por ejemplo 

2.- Create a file called routers.py, where a class is defined by overwriting some methods

class DatabaseRouter(object):
def db_for_read(self, model, **hints):
    request = HttpRequest()
    if request.META.get('HTTP_HOST) == 'domain1':
        return 'database1'
    if request.META.get('HTTP_HOST) == 'domain2':
        return 'database2'
    return None

def db_for_write(self, model, **hints):
    request = HttpRequest()
    if request.META.get('HTTP_HOST) == 'domain1':
        return 'database1'
    if request.META.get('HTTP_HOST) == 'domain2':
        return 'database2'
    return None

def allow_syncdb(self, db, model):

    if db == 'database1' or db == 'database2':
        return model._meta.app_label == 'app'
    elif model._meta.app_label == 'app':
        return False

    return None

that class is integrated into Settings.py

DATABASE_ROUTERS = ['APIapp.routers.DatabaseRouter',]

So far the information is good.

Now, the question is: How can I make it so that when I enter the domain, routers.py knows which domain and therefore what database to choose?

According to what I have read, doing it through a middleware but I could not, then I think of recovering it in routers.py the domain. The Django views contain a request argument where it includes the hostname, but I could not retrieve that Django object and send it to routers.py

What can I do?

    
asked by JOCarrizoza 05.01.2018 в 19:01
source

1 answer

0

Well yes, the best way was through a middleware and now routers.py is like this:

from django.utils.deprecation import MiddlewareMixin
from django.conf import settings
from django.http import Http404
import threading
request_cfg = threading.local()

class RouterDBMiddleware(MiddlewareMixin):
    def process_view( self, request, view_func, args, kwargs ):
        for db_name in settings.DATABASE_CURSORS:
            if db_name in request.get_host():
                request_cfg.db = db_name
        if not request_cfg:
            request_cfg.db = 'default'

    def process_response(self, request, response):
        if hasattr(request_cfg, 'db'):
            del request_cfg.db
        return response

class DatabaseRouter(object):
    def _default_db( self ):
        if hasattr( request_cfg, 'db' ):
            return request_cfg.db
        else:
            return 'default'

    def db_for_read(self, model, **hints):
        return self._default_db()
    def db_for_write(self, model, **hints):
        return self._default_db()
    def allow_syncdb(self, db, model):
        if db == request_cfg.db:
            return model._meta.app_label == 'APIapp'
        elif model._meta.app_label == 'APIapp':
            return False
        return None

In settings.py declare a list with the values of the databases to call it

DATABASE_CURSORS = ['interprice','prueba1','prueba2']

The middleware

'APIapp.routers.RouterDBMiddleware',

and the router

DATABASE_ROUTERS = ['APIapp.routers.DatabaseRouter',]

and it worked !!!

I share the leagues from which I base:

link

link

link

link

    
answered by 05.01.2018 в 23:32