0

Is it possible for Django to use the same link and a database for each client?

Hello, I'm new to Django and I have a question. I'm bringing a PHP system to Django where all clients use the same link to access the system, but each with its database with users, access groups, etc. In the custom login screen they inform their client id, user and password to authenticate, where always the client id is the name of the database.

I made the following code to change the database connection that is probably wrong:

def change_db (self):
    connections ['default']. settings_dict ['NAME'] = self.db
    return True

The code even exchanges the database I want to access, but testing on my local machine using the runserver, if another client is accessing simultaneously for example in another browser, it displaces the other client.

Has anyone had it or does it have an idea to solve? I searched the routers, I do not know if I would solve my problem, or if there was the same problem of switching the connection and removing the other client.

Grateful.

ayrtonmoises
  • 66
  • 1
  • 3
  • 1
    As far as I know the settings are *immutable*. It would be dangerous to change settings at runtime, since several Django parts are not design to handle such changes. – Willem Van Onsem Jun 06 '18 at 17:09
  • I understand, django would not have a better way of choosing the database that the user would work on? Maybe something per session where it would not change settings? – ayrtonmoises Jun 06 '18 at 18:45
  • yes, you can for example use database routing: https://docs.djangoproject.com/en/2.0/topics/db/multi-db/#using-routers – Willem Van Onsem Jun 06 '18 at 18:47
  • I will try with routers, if you get results I inform you – ayrtonmoises Jun 06 '18 at 19:22

2 Answers2

1

I think I solved my problem, I found a link that was very useful to me:

dynamically set database based on request in django

It uses a middleware to get the connection and router as mentioned by the staff that responded, which in the case it takes the subdomain, I made some changes in it to get the prefix that already solves my case, with the help of this link:

Django URL with dynamic prefix

Follow the code:

from django.utils.deprecation import MiddlewareMixin
from django.contrib.sessions.middleware import SessionMiddleware
import re
import threading 

request_cfg = threading.local()

#Middleware
class RouterMiddleware(MiddlewareMixin):

    def process_request(self, request):
        words = request.get_full_path()
        db_name = words.split('/')[1]
        request_cfg.cfg = db_name
        return None

    def process_view(self, request, view_func, view_args, view_kwargs):
        cliente = view_kwargs.get('cliente')
        if cliente:
            request.cliente = cliente
            view_kwargs.pop('cliente')
            return view_func(request, *view_args, **view_kwargs)

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

#Router
class DatabaseRouter (object):
    def _default_db(self):
        if hasattr(request_cfg, 'cfg'):
            return request_cfg.cfg
        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()

Thank you to anyone who tried to help me :)

ayrtonmoises
  • 66
  • 1
  • 3
-1

According to docs, you should not edit settings.py at runtime, but did you tried this?

  • Please don't link to an answer, put the relevant content in your answer. – gilliduck Jun 06 '18 at 17:36
  • I tried this just for testing, so I'm behind the best solution to switch the connection according to the logged-in user, without having this problem of swapping the database globally when another client logs in. – ayrtonmoises Jun 06 '18 at 18:47