2013-03-07 24 views
24

Mam asortyment podobnych (ale nie identycznych) baz danych i chciałbym użyć SQLAlchemy jako sposobu na "standaryzację" dostępu. Bazy danych mogą się nieznacznie różnić, na przykład o unikalnym przedrostku na nazwach kolumn lub mogą się znacznie różnić i brakować kolumn (lub starych baz danych, brakujących całych tabel).SQLAlchemy i wiele baz danych

To, czego szukam, to nie tyle problem z SQLAlchemy, co Python/Organizational. Jak mogę mieć wiele konfiguracji baz danych, które mogą być ponownie użyte w projektach?

Przeczytałem o sesjach SQLAlchemy, ale nie widzę sposobu ich użycia bez tworzenia każdego z nich w każdym projekcie.

Moje pytanie brzmi: jak mogę zrobić moduł/pakiet, który będzie zawierał wiele ustawień modelu bazy danych do użycia w SQLAlchemy, które można łatwo zaimportować/wykorzystać w innym projekcie pythona?

Nie martwię się o brakujące kolumny/tabele. Mogę rozwiązać ten problem później, ale jest to coś, o czym należy pamiętać, ponieważ nie mogę użyć dokładnie tego samego modelu dla każdej bazy danych.

Wszelkie zasoby, wskaźniki lub materiały do ​​czytania na ten temat będą naprawdę mile widziane. Z góry dziękuję i przepraszam, jeśli odpowiedź została udzielona w innym miejscu, w wyszukiwaniach nie wykazano niczego z tym związanego.

EDYTOWANIE: Pozostawiłem oryginał nienaruszony i dodam więcej treści na podstawie porad Pawła.

RE: SA ORM - Tak, planuję użyć ORM SQLAlchemy. Z oczywistych powodów nie mogę dostarczyć prawdziwych baz danych. Załóżmy jednak te trzy fikcyjne bazy danych, trafnie nazwane DB1, DB2 i DB3 (przyjmiemy jedną tabelę w każdej, z zaledwie kilkoma kolumnami, rzeczywisty świat będzie miał znacznie więcej z obu).

Każda baza danych ma tabelę użytkowników z kilkoma kolumnami w każdej. Poniżej przedstawiono niektóre notacja SQL dla tabel/kolumn:

DB1.user --> DB1.user.id,  DB1.user.username, DB1.user.email 
DB2.user --> DB2.user.id,  DB2.user.user_name, DB2.user.email 
DB3._user --> DB3._user.userid, DB3._user.username, DB3.user.email_address 

Obecnie staram się oddzielić tych baz danych do „modułowy”, i być w stanie po prostu dodanie dodatkowych baz danych jak idę.

mam rozważymy aspekty organizacyjne para inny plik (zakładamy __init__.py gdzie istnieje taka potrzeba, ale pominięte przez wzgląd na zwięzłości), w tym:

Databases   | Databases   | Databases 
    DB1.py  |  DB1    |  DB1 
    DB2.py  |   models.py |   models 
    DB3.py  |  DB2    |    user.py 
        |   models.py |    anothertable.py 
        |  DB2    |  ... 
        |   models.py |  DB3 
        |       |   models 
        |       |    user.py 
        |       |    anothertable.py 

chciałbym mieć dostęp do nich z SAM ORM i rób to przy jak najmniejszej ilości importów/deklaracji, gdy przychodzi czas na użycie tych baz danych w pliku Pythona. Konieczność zrobienia czegoś podobnego do:

from sqlalchemy import create_engine 
from sqlalchemy.orm import sessionmaker 
from Database import DB1, ..., DB[N] 
db1_engine = create_engine('connect_string/db1') 
db1_session = sessionmaker(bind=db1_engine)() 
... 
db3_engine = create_engine('connect_string/db3') 
db3_session = sessionmaker(bind=db3_engine)() 

byłoby niewiarygodnie kłopotliwe, ponieważ będę miał do czynienia z czymś więcej niż trzema bazami danych. Wolałbym mieć już załatwione dla mnie

Będąc w stanie uzyskać dostęp i używać go podobnym do (w pliku __init__.py, może?):

import Databases 

Databases.DB1.session.query('blahblah') 

byłoby nieskończenie lepsze.

EDIT2: Wiem również, jak obejść warianty konwencji nazewnictwa baz danych/kolumn podczas konfigurowania moich modeli. To nie jest problem, ale wspomniałem o tym, aby było wiadomo, że nie mogę po prostu użyć jednego zestawu modeli dla wielu baz danych.

Mam nadzieję, że rozszerzając to, nie zabrudziłem wód ani nie zrobiłem tego zbyt zagmatwanego. Dziękujemy za poświęcenie czasu na przeczytanie!

EDIT3: Udało mi się poświęcić temu więcej czasu. Wcześniej skonfigurować projekt w następujący sposób:

Databases 
    __init__.py 
    databases.py 
    settings.py 
    DB1 
     __init__.py 
     models.py 
    ... 
    DB3 
     __init__.py 
     models.py 

Obecnie mam tupple baz danych, które są „zainstalowane” w pliku settings.py. Każdy wpis ma być podobny do INSTALLED_DATABASES = ('DB1', ..., 'DB3'). Gdy uzupełniam więcej modeli, zostaną one dodane do listy tupples. To pozwala mi dodawać lub usuwać zawartość w trakcie mojej podróży.

Mam ustawienia silnika i sessios w pliku models.py oraz plik init.py dla każdej konfiguracji bazy danych do from models import *.

W pliku databases.py Mam następujący

class Databases(object): 
    def __init__(self): 
     for database in INSTALLED_DATABASES: 
      setattr(self, database, __import__(database)) 

Teraz mogę z nich korzystać za pomocą:

from databases import Databases 

db = Databases() 

for qr in db.DB1.query(db.DB1.User): 
    print qr.userid, qr.username 

SQLAlchemy jest umożliwienie mi ręcznie określić nazwy kolumn przy definiowaniu modeli, które to ogromny bonus do pożądanej przeze mnie standaryzacji.

Mam jeszcze przed sobą dużo pracy. Chciałbym tworzyć obiekty, które wymuszają sprawdzanie poprawności modelu (tj. Czy pole jest obecne? Czy pole nieobecne ma wartość domyślną? Itd.) I lepiej uwzględnia to, jak to działa z moim IDE (to obecnie nie ma). Ale jestem na dobrej drodze. Pomyślałem, że zaktualizuję to dla każdego, kto może przez przypadek zastanawia się, jak zrobić to samo, co ja.

Przepraszam, że to stało się tak długo!

Pozdrawiam!

+0

Dodałem kilka dodatkowych informacji do tego jako EDIT3. Mam go * trochę * działa jak chcę, ale będę musiał go ulepszyć. Będę musiał kontynuować tę kwestię w różnych kwestiach, ponieważ zakres odpowiedzi na oryginał został rozwiązany. Nie oczekuję więc, że to zaktualizuję, chyba że zmienię coś drastycznego lub zrobię poważny postęp w jego działaniu. Jeśli ktoś ma jakieś sugestie, jak to zrobić lepiej, ja jestem wszystkimi uszami. Dziękuje za przeczytanie. – Rejected

+0

Nie jestem pewien, czy to pomoże, ale może może dodać coś do swojej. To jest post od zzeka i podczas czytania twojego pytania częściowo mi o tym przypomniano: http://techspot.zzzeek.org/2012/01/11/django-style-database-routers-in-sqlalchemy – javex

+0

Gorąco polecam Biorąc ostatnią zmianę i czyniąc ją odpowiedzią - jest dobra i odpowiadając na własne pytanie, uśmiecha się tutaj :-) –

Odpowiedz

5

Zgodnie z wnioskami do mojego pierwotnego pytania, wziąłem moją trzecią edycję i sprawiły, że moja odpowiedź. Ponieważ nie jestem pewien prawidłowych protokołów, zostawiłem trzecią edycję powyżej.Jeśli już czytałeś EDIT3, to przeczytałeś, co mam jako odpowiedź.

Udało mi się poświęcić temu trochę więcej czasu. Wcześniej skonfigurować projekt w następujący sposób:

Databases 
    __init__.py 
    databases.py 
    settings.py 
    DB1 
     __init__.py 
     models.py 
    ... 
    DB3 
     __init__.py 
     models.py 

Obecnie mam tupple baz danych, które są „zainstalowane” w pliku settings.py. Każdy wpis ma być podobny do INSTALLED_DATABASES = ('DB1', ..., 'DB3'). Gdy uzupełniam więcej modeli, zostaną one dodane do listy tupples. To pozwala mi dodawać lub usuwać zawartość w trakcie mojej podróży.

Mam ustawienia silnika i sessios w pliku models.py oraz plik init.py dla każdej konfiguracji bazy danych do from models import *.

W pliku databases.py Mam następujący

class Databases(object): 
    def __init__(self): 
     for database in INSTALLED_DATABASES: 
      setattr(self, database, __import__(database)) 

Teraz mogę z nich korzystać za pomocą:

from databases import Databases 

db = Databases() 

for qr in db.DB1.query(db.DB1.User): 
    print qr.userid, qr.username 

SQLAlchemy jest umożliwienie mi ręcznie określić nazwy kolumn przy definiowaniu modeli, które to ogromny bonus do pożądanej przeze mnie standaryzacji.

Mam jeszcze przed sobą dużo pracy. Chciałbym tworzyć obiekty, które wymuszają sprawdzanie poprawności modelu (tj. Czy pole jest obecne? Czy pole nieobecne ma wartość domyślną? Itd.) I lepiej uwzględnia to, jak to działa z moim IDE (to obecnie nie ma). Ale jestem na dobrej drodze. Pomyślałem, że zaktualizuję to dla każdego, kto może przez przypadek zastanawia się, jak zrobić to samo, co ja.

Przepraszam, że to stało się tak długo!

Pozdrawiam!

1

Twoje rozwiązanie wygląda całkiem nieźle. Oto co zrobiłem.

Mam pakiet o nazwie złącza, aw nim moduł dla każdego db, a także plik ustawień.

Każdy z tych modułów złącza tworzy ciąg połączenia i jego silnik, wraz z deklaratywną podstawą i klasami dla tabel.

Następnie jest metoda loadSession, która zwraca sesję (ta, którą dostałem z tutoriala lub innego posta tutaj gdzieś, nie pamiętam dokładnie) i jeszcze jedną dodałem, która zwraca silnik na wypadek, gdy chcę coś z tym zrobić .

Więc w jakiś inny moduł programu, chciałbym zrobić coś takiego

from connectors import x, y, z 

x_ses = x.loadSession() 
y_ses = y.loadSession() 
z_ses = z.loadSession() 

xq = x_ses.query(...) 
yq = y_ses.query(...) 
Powiązane problemy