2013-01-10 19 views
14

Nel mio progetto Django ho una dipendenza per un'applicazione di terze parti che produce file di cache SQLite in varie directory con uno schema noto.Django: file di database dinamico

Mi piacerebbe utilizzare i modelli Django per accedere a quei database, ma ovviamente non posso usare un setup statico DATABASES.

Come è possibile aprire dinamicamente un database SQLite su un percorso arbitrario?

EDIT

Come Byron Ruth sottolineato, la soluzione è utilizzare il django.db.connections in combinazione con la funzione using nel QuerySet.

+0

perché non è possibile utilizzare i database? Da quello che vedo questo perché gli autori di Django ce l'hanno fatta! L'altra opzione è usare raw sql (http://docs.python.org/2/library/sqlite3.html), ma in qualche modo sconfigge lo scopo di un framework! – StefanNch

+0

@StefanNch: Non riesco a utilizzare l'installazione di 'DATABASES' perché non posso sapere a quali database andrò a finire, perché sono aggiunti * dinamicamente *. E sì, sto usando l'API sqlite3, di cui non sono completamente soddisfatto perché non voglio scavare in SQL. – Constantinius

+0

questa è un'architettura interessante, ma ora vedo il tuo problema ... – StefanNch

risposta

29

Il django.db.connections è un semplice wrapper DATABASES definito nel impostazioni. La classe wrapper è qui: 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'] 
+1

Penso che questa sia la soluzione che stavo cercando. Lo proverò! – Constantinius

+0

Questo è stato, sono stato in grado di selezionare dinamicamente un file di database, aprirlo e utilizzare i miei modelli. (questo richiede la funzione 'using' sul queryset, però). – Constantinius

+0

bello! hmmm ... quindi questa connessione deve essere aggiunta per ogni richiesta in entrata che deve usare il db? Potrebbe essere bello racchiudere questo in alcuni middleware per configurare il db al momento della richiesta ... – monkut

4

È possibile registrare il database nelle impostazioni DATABASE.

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 

Si può ma non si dovrebbe.

+0

Questo sembra interessante, farò un tentativo. Ma preferirei una soluzione in cui non dovessi modificare l'impostazione di 'DATABASES'. – Constantinius

+1

Non modificare le impostazioni nelle applicazioni in fase di esecuzione. Ad esempio, non fare questo in una vista: https://docs.djangoproject.com/en/dev/topics/settings/#altering-settings-at-runtime –

2

Supponendo che l'unico motore usato è SQLite e la posizione del (solo) file di database è quello che varia, fornire un callable al 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 
    } 
} 
+0

Vorrei secondo questo. Se le posizioni dei DB cambiano in modo dinamico durante il runtime, assicurati che get_db_loc() cambi il suo comportamento in base al DB attualmente attivo (memorizza le informazioni in un file di testo/var globale), quindi all'interno di get_db_loc() in tempo reale reindirizza al DB attualmente attivo. –

+1

Non sono sicuro che funzionerà, perché la funzione 'get_db_loc' viene valutata solo una volta, e non ogni volta che viene letto il' DATABASES'. Ma altrimenti grazie per il contributo. – Constantinius

+0

Giusto, non c'è modo che questo possa funzionare. Il risultato di 'get_db_loc()' è solo una stringa. Non c'è niente di speciale nel fatto che è stato ottenuto chiamando una funzione, e non c'è nulla che dice di chiamare di nuovo quella funzione. – rspeer

Problemi correlati