Change default db for django.contrib.auth

I have two db in my project and two routes, but when i try login in my app othe default db dont use django.contrib.auth of my other db

DATABASES = {
    'default': {
        'ENGINE': os.getenv('DB_PRODUCTION_ENGINE', 'change-me'),
        'NAME': os.getenv('POSTGRES_PRODUCTION_DB', 'change-me'),
        'USER': os.getenv('POSTGRES_PRODUCTION_DB_USER', 'change-me'),
        'PASSWORD': os.getenv('POSTGRES_PRODUCTION_DB_PASSWORD', 'change-me'),
        'HOST': os.getenv('POSTGRES_PRODUCTION_HOST', 'change-me'),
        'PORT': os.getenv('POSTGRES_PRODUCTION_PORT', 'change-me'),
        'TEST': {
            "ENGINE": "django.db.backends.sqlite3",
            "NAME": "test_prod_db.sqlite3",
        },
    },
    'development': {
        'ENGINE': os.getenv('DB_DEVELOPMENT_ENGINE', 'change-me'),
        'NAME': os.getenv('POSTGRES_DEVELOPMENT_DB', 'change-me'),
        'USER': os.getenv('POSTGRES_DEVELOPMENT_DB_USER', 'change-me'),
        'PASSWORD': os.getenv('POSTGRES_DEVELOPMENT_DB_PASSWORD', 'change-me'),
        'HOST': os.getenv('POSTGRES_DEVELOPMENT_HOST', 'change-me'),
        'PORT': os.getenv('POSTGRES_DEVELOPMENT_PORT', 'change-me'),
        'TEST': {
            "ENGINE": "django.db.backends.sqlite3",
            "NAME": "test_dev_db.sqlite3",
        },
    }
}

What does your router look like?

Also, see the caveats and issues at Limitations of multiple databases

My routes look like this

class DevRouter:
    route_app_labels = {
        "users_dev",
        "arts_dev",
        "authentication_dev",
        "collaborators_dev",
        "dashboard_dev",
        "languages_dev",
        "library_dev",
        "plans_dev",
        "workspaces_dev",
        "templates_dev",
        "templatefields_dev",
        "questions_dev",
        "groups_dev",
        "filters_dev",
        "categories_dev",
        "subcategories_dev",
        "interests_dev",
        "usecases_dev",
        "resources_dev",
    }

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return "development"
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return "development"
        return None

    def allow_relation(self, obj1, obj2, **hints):
        if (
            obj1._meta.app_label in self.route_app_labels
            or obj2._meta.app_label in self.route_app_labels
        ):
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label in self.route_app_labels:
            return db == "development"
        return None

my problem in my view what use ‘from django.contrib.auth.models import User’ and try authenticate, dont use db development

authentication_dev/view.py

class LoginView(View):
    def get(self, request):
        login_form = LoginForm()
        return render(
            request,
            'authentication_dev/pages/login.html',
            context={
                'login_form': login_form
            }
        )

    def post(self, request):
        login_form = LoginForm(request.POST)

        if login_form.is_valid():
            user = authenticate(
                username=login_form.cleaned_data.get('username', ''),
                password=login_form.cleaned_data.get('password', '')
            )
            if user:
                messages.success(request, 'Login realizado com sucesso!')
                login(request, user)
                return redirect(
                    reverse('dashboard_dev:index')
                )
            else:
                messages.warning(request, 'CredĂȘnciais invĂĄlidas')
        else:
            messages.warning(request, 'E-mail ou senha invĂĄlido')
        return redirect(
            reverse('authentication_dev_dev:login')
        )

That’s because you don’t have auth in your route_app_labels.

Note: If you’re looking to have the same code for development and production, and route everything to development when in development, this is not the way to do this.

You’re already using environment variables for your database settings. Have one database definition, all using the same environment variables for the settings, and set those variables based upon whether you need to run in development or production.

There are other ways to handle this as well, but basically, pretty much anything else is going to be better than trying to do it this way.

I use this form, because i need change the databases in runtime. This way was the best I found.
Continuing the question when i set “auth” in route this will not change the db to only the development db

That’s an even worse idea - especially in a production-style environment, where you may have different wsgi process instances running and being restarted at arbitrary times, and may end up with different instances referencing the two different databases. This means that at a minimum, you will want to restart your app when you change databases - and when you’re doing so, you can reset the environment variables at that same time.

I don’t know what situation or issue that you’re looking to address here, or what your deployment environment looks like, but whatever it is, I would strongly suggest you take a step back and look at it from a broader perspective. Continuing along this route is going to put you in a situation where you’re trying to resolve erratic and irregular results.

I try explain for you.

I have a website management system and the client has two db, it’s db for production and db for development, practically the same. The client asked me to have a view in the system view where he can select the database he wants to use

My recommendation for this would be to deploy two instances of your project with either two different ports for access or two different base urls or even two different (sub)domain names - each instance configured for the different databases. You’re going to avoid a lot of problems that way.
(Note, it can still be the same code. You do not need to deploy two copies of the project. They just need to be configured to be accessed two different ways.)

Do you say that “instances” are two distinct projects for each DB? and in NGINX I configurate the distincts ports

Yes, one instance of the application for each database.

Yes, using nginx you could either separate them by path, port, and/or (sub)domain name. Entirely up to you.

1 Like