'Python Django ORM select custom DB for raw query by session variable

Given the following raw query, inside a view:

@login_required(login_url='/login/')
def view(request):
    result = CustomObject.objects.raw("SELECT a, b, c FROM table WHERE d = %(param)s", {
        'param': 123
    })

    ...

    return render(request, 'templates/template.html', {
        'a': 'b'
    })

I use a router to route the query to a DB (use case is read only).

class MyDBRouter(object):
    @staticmethod
    def db_for_read(model, **hints):
        if model == CustomObject:
            return 'customdb'
        return None

    @staticmethod
    def db_for_write(model, **hints):
        return None

I have the available databases configured:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    },
    'customdb': {
        'ENGINE': 'django.db.backends.oracle',
        'NAME': 'xxx.yyy.zzz:1234/DB',
        'USER': 'user',
        'PASSWORD': 'pass',
    }
}

Problem:

During login, the User can specify which database he wants to execute the commands on. Depending on the session, I have to use different databases to connect to, therefore I have to specify manually for each request which DB it goes to.

Question:

  • How can I access my session variables from a static method of a router?
  • If using routers is not advised in this specific case, what other options do I have for this problem?


Solution 1:[1]

I don't think you need to do this way

If you need to use custom database on the fly you can pass it in

def login(request):
    # Your logic
    request.session["db-name"] = "customdb"
    # Your logic

def query_view(request):
    db_name = request.session.get("db-name", "default")
    # execute your query with this db_name like 

    MyModel.objects.using(db_name).raw("Your query")

Also if you want your session key to be unique then you can use unique username also like this

request.session[f"{request.user.username}_{db_name}"] = "customdb"

And access it in other views.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Deepak Tripathi