16
votes

In my Django project I have a dependency for a third party application that produces SQLite cache files in various directories with a known schema.

I'd like to use Django models to access those databases, but obviously I cannot use a static DATABASES setup.

How can I dynamically open a SQLite database on an arbitrary path?

EDIT

As Byron Ruth pointed out, the solution is to use the django.db.connections in conjunction with the using function in the QuerySet.

3
why cannot use DATABASES? From what I see this why the authors of Django made it! The other option is to use raw sql (docs.python.org/2/library/sqlite3.html), but kinda defeats the purpose of a framework! - StefanNch
@StefanNch: I cannot use the DATABASES setup because I cannot know what databases I'll end up with, because they are added dynamically. And yes, I'm currently using the sqlite3 API, which I'm not fully content with as I do not want to dig into SQL. - Constantinius
thats an interesting architecture, but now I see your issue ... - StefanNch

3 Answers

33
votes

The django.db.connections is a simple wrapper around DATABASES defined in your settings. The wrapper class is here: django.db.utils#L137-L227

from django.db import connections

# Add connection information dynamically..
connections.databases['new-alias'] = { ... }
# Ensure the remaining default connection information is defined.
# EDIT: this is actually performed for you in the wrapper class __getitem__
# method.. although it may be good to do it when being initially setup to
# prevent runtime errors later.
# connections.databases.ensure_defaults('new-alias')

# Use the new connection
conn = connections['new-alias']
4
votes

You can register database in DATABASES settings.

from your_project import settings
database_id = "unqique_name"
new_database = {}
new_database["id"] = database_id
new_database['ENGINE'] = 'django.db.backends.sqlite3'
new_database['NAME'] = '/project/data/db_%s.sql' % database_id
new_database['USER'] = ''
new_database['PASSWORD'] = ''
new_database['HOST'] = ''
new_database['PORT'] = ''
settings.DATABASES[database_id] = new_database

You can but you shouldn't.

1
votes

Assuming the only engine used is SQLite and the location of the (only) database file is what varies, provide a callable to the NAME:

def get_db_loc():
    # code to determine filesystem location of database
    return location

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': get_db_loc(),
        # More config goes here
    }
}