2013-01-10 8 views
14

W moim projekcie Django mam zależność od aplikacji innej firmy, która produkuje pliki pamięci podręcznej SQLite w różnych katalogach ze znanym schematem.Django: dynamiczny plik bazy danych

Chciałbym użyć modeli Django, aby uzyskać dostęp do tych baz danych, ale oczywiście nie mogę użyć statycznego ustawienia DATABASES.

Jak mogę dynamicznie otwierać bazę danych SQLite na dowolnej ścieżce?

EDIT

jako Byron Ruth wspomniano, rozwiązanie polega na użyciu django.db.connections w połączeniu z funkcją w queryset using.

+0

dlaczego nie mogą korzystać z baz danych? Z tego, co widzę, przyczynili się twórcy Django! Inną opcją jest użycie surowego sql (http://docs.python.org/2/library/sqlite3.html), ale w pewnym sensie pokonuje to cel ramy! – StefanNch

+0

@StefanNch: Nie mogę użyć konfiguracji 'DATABASES'', ponieważ nie wiem, z jakich baz danych skończę, ponieważ są one dodawane * dynamicznie *. Tak, używam obecnie API sqlite3, z którego nie jestem w pełni zadowolony, ponieważ nie chcę przekopywać się do SQL. – Constantinius

+0

to interesująca architektura, ale teraz widzę twój problem ... – StefanNch

Odpowiedz

29

django.db.connections jest proste otoki wokół DATABASES zdefiniowanych w ustawienia. Klasa wrapper jest tutaj: 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

Myślę, że jest to rozwiązanie, którego szukałem. Dam temu szansę! – Constantinius

+0

To było to, byłem w stanie dynamicznie wybrać plik bazy danych, otworzyć go i korzystać z moich modeli. (wymaga to jednak użycia funkcji 'using' w zapytaniu). – Constantinius

+0

fajnie! hmmm ... więc to połączenie należy dodać do każdego przychodzącego żądania, które musi korzystać z bazy danych? Może być fajnie opakować to w jakieś oprogramowanie pośrednie, aby skonfigurować db jako żądanie przychodzi w ... – monkut

4

Możesz zarejestrować bazę danych w ustawieniach DATABASES.

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 

Możesz, ale nie powinieneś.

+0

To wygląda interesująco, spróbuję. Ale wolę rozwiązanie, w którym nie będę musiał zmieniać ustawienia 'DATABASES'. – Constantinius

+1

Nie powinieneś zmieniać ustawień w aplikacjach w środowisku wykonawczym. Na przykład nie rób tego w widoku: https://docs.djangoproject.com/en/dev/topics/settings/#altering-settings-at-runtime –

2

Zakładając, że tylko silnik używany jest SQLite i lokalizacja (tylko) pliku bazy danych jest to, co się zmienia, zapewniają wywoływalnym do 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

Chciałbym to powtórzyć. Jeśli lokalizacje DB zmieniają się dynamicznie w czasie wykonywania, upewnij się, że get_db_loc() zmienia swoje zachowanie na podstawie tego, która baza danych jest aktualnie aktywna (przechowuj te informacje w pliku tekstowym/globalnym var), a następnie wewnątrz get_db_loc() w czasie rzeczywistym przekierowanie do aktualnie aktywny DB. –

+1

Nie jestem pewien, czy to zadziała, ponieważ funkcja 'get_db_loc' jest oceniana tylko raz, a nie za każdym razem, gdy czytane jest' BAZY DANYCH'. Ale poza tym dziękuję za wkład. – Constantinius

+0

W porządku, nie ma sposobu, żeby to zadziałało. Wynikiem 'get_db_loc()' jest tylko ciąg znaków. Nie ma nic szczególnego w tym, że został uzyskany przez wywołanie funkcji, i nie ma nic, co by wskazywało na to, że kiedykolwiek wywołasz tę funkcję ponownie. – rspeer

Powiązane problemy