[Django]-Django Authenticate Backend Multiple Databases

8👍

Since the auth backend is not calling the QuerySet method using you could use a database router with a thread local variable and some middleware to set the variable to the customer’s database name. The middleware would have to be placed before the authentication middleware.

The thread local variable is thread safe. It creates a thread local global variable.

If you were following the path of a request it would do the following:

  1. The request hits django
  2. Your custom middleware grabs the database name from the url sets it to the thread local global variable.
  3. The django authentication middleware starts and sets the user by running the query User.object.get(id=user_id). This will use your database router which will just return the thread local global variable that was set in the previous middleware.

  4. The request continues into the rest of the django stack.

For example you have the following modules:

my_app/middleware.py

from threading import local

my_local_global = local()

class CustomerMiddleware(object):
    def process_request(self, request):
        my_local_global.database_name = get_database_name(request)

my_app/routers.py

from middleware import my_local_global

class MultiCustomerRouter(object):
    def db_for_read(self, model, **hints):
        return my_local_global.database_name

settings.py

...
MIDDLEWARE_CLASSES = (
 'django.middleware.common.CommonMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'my_app.middleware.CustomerMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
)

DATABASE_ROUTERS = ['my_app.routers.MultiCustomerRouter']
...
👤tharps

2👍

Its likely you could use the Django database routers to control this. If you know which user hits which database you could simply define that based on logic for the user model.

Leave a comment