Динамическое создание экземпляра базы данных django

В веб-приложении django при входе в систему я сохраняю имя базы данных в сеансе. Мне нужен метод для динамического создания экземпляра базы данных с использованием этого имени, которое сохраняется в пользовательском сеансе. Я не хочу использовать "using()", потому что мое приложение уже выполнено, и это потребовало бы от меня много работы, ни путем настройки нескольких баз данных в ваших настройках (потому что мои базы данных создаются динамически), если есть другой способ, который я хотел бы знать. Может быть, это и невозможно, я пойму, если это так...

Я пробовал промежуточные программы, маршруты, потоки, декораторы, но, возможно, я бы сделал что-то не так. Я исчерпал все свои попытки. Насколько я мог, я регистрировался в нужной базе данных до тех пор, пока на втором экране моего приложения, когда я просматриваю приложение, на 3-м экране, который я просматриваю, база данных не возвращается к значению по умолчанию.

промежуточное программное обеспечение:

import re
from django.utils.deprecation import MiddlewareMixin
from django.db import connections
from .thread import set_banco_academia

class DatabaseMiddleware(MiddlewareMixin):
    def process_request(self, request):
        """
        Middleware que define dinamicamente o banco de dados a ser usado
        com base na sessão do usuário e adiciona a conexão ao Django.
        """
        if not hasattr(request, "session"):  # Garante que a sessão foi carregada
            return

        # Obtém o banco armazenado na sessão ou usa "default"
        banco_academia = request.session.get("banco_academia", "default")

        print(f"🔍 Banco selecionado na sessão: {banco_academia}")

        # Valida o nome do banco para evitar SQL Injection
        if self.is_valid_database_name(banco_academia):
            set_banco_academia(banco_academia)
        else:
            set_banco_academia("default")
            banco_academia = "default"

        # Se o banco ainda não estiver em connections, adicionamos dinamicamente
        if banco_academia not in connections.databases:
            connections.databases[banco_academia] = {
                'ENGINE': 'django.db.backends.mysql',  # Ou outro engine
                'NAME': banco_academia,
                'USER': 'root',
                'PASSWORD': '',
                'HOST': 'localhost',
                'PORT': '3306',
                'ATOMIC_REQUESTS': False,
                'AUTOCOMMIT': True,
                'CONN_MAX_AGE': 0,
                'CONN_HEALTH_CHECKS': False,
                'OPTIONS': {},
                'TIME_ZONE': None,
                'TEST': {
                    'CHARSET': None,
                    'COLLATION': None,
                    'MIGRATE': True,
                    'MIRROR': None,
                    'NAME': None,
                },
            }
            print(f"🔗 Conexão adicionada dinamicamente para o banco: {banco_academia}")

    def is_valid_database_name(self, name):
        """Valida se o nome do banco é seguro e segue um padrão esperado"""
        return bool(re.match(r"^[a-zA-Z0-9_]+$", name))

нарезание резьбы:

import threading

_local = threading.local()

def set_banco_academia(banco):
    """Define o banco de dados na thread local"""
    _local.banco_academia = banco

def get_banco_academia():
    """Obtém o banco de dados armazenado na thread local"""
    return getattr(_local, "banco_academia", "default")

маршрутизатор:

from django.db import connections
from .thread import get_banco_academia

class ClubGymRouter:
    def db_for_read(self, model, **hints):
        """Define o banco de leitura dinamicamente"""
        banco_academia = get_banco_academia()
        if banco_academia in connections.databases:
            return banco_academia
        return "default"

    def db_for_write(self, model, **hints):
        """Define o banco de escrita dinamicamente"""
        banco_academia = get_banco_academia()
        if banco_academia in connections.databases:
            return banco_academia
        return "default"

    def allow_relation(self, obj1, obj2, **hints):
        """Permite relações entre objetos do mesmo banco"""
        db_set = {get_banco_academia(), "default"}
        return obj1._state.db in db_set and obj2._state.db in db_set

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """Define se a migração pode ser feita no banco correto"""
        return db == get_banco_academia() or db == "default"

вот как я сохраняю имя базы данных в сеансе

request.session["banco_academia"] = nome_banco
request.session.modified = True  # 🔥 Marca como modificada
request.session.save()
Вернуться на верх