Multiple dynamic database access

I’m wondering if it’s possible to use the ORM to declare external models that won’t be managed, migrated. Mostly to query/insert data.
These “external” models will be in fact related to a specific set of users, and i ain’t able to set the connections parameters on the settings.DATABASES configuration, since this will change, grow overtime. These configurations will be stored on default database. I’m trying to declare these external models with the ORM so i can abstract the connection, sql and to_python casting.

Searching on the django docs for multiple databases, i see this statement:

If you attempt to access a database that you haven’t defined in your DATABASES setting, Django will raise a django.utils.connection.ConnectionDoesNotExist exception.

And since it’s not recommended to change settings at runtime, i wonder if there’s a way to dinamically connect and use a database like said.
I’ve seen some posts that are related, but not totally for what i’m trying to achieve. Also there was a package that was doing somewhat i’m expecting, but it’s no longer maintained.

Yes, the connections.databases object is a dict that you can augment at runtime.

We do something like this where an individual can add a database connection through a table entry. The connection is added dynamically when added, and then the connection information is stored in a table to be initialized the next time the app is started.

Adding a connection:
connections.databases[connection_name] = some_database_definition_dict
where connection_name is the name of the connection to be used in the using method and some_database_definition_dict is a Python dict of the format used in the DATABASES settings.

Note: In a multi-process situation, this also involves a lot of error checking in views to catch or prevent key errors in the database. (We add a test to each view to verify that the named connection is present at the beginning of the view.)

What you don’t want to do is change one of these entries after they’ve been added.

1 Like

Thanks for the reply @KenWhitesell.
I wonder where the best place for this loading on startup is.
Maybe on the app.ready function? I think that this function is called every time the application startup.

As a matter-of-fact, that’s exactly where we do it.

From our apps.py file:

class BrowserConfig(AppConfig):
    ...
    def ready(self):
        from browser.models import DatabaseConnection
        for conn in DatabaseConnection.objects.all():
            connections.databases[conn.connection_name] = conn.get_config()
    ...

2 Likes

Thanks @KenWhitesell!