Mam przykład, jak to zrobić na moim blogu pod adresem http://techspot.zzzeek.org/2012/01/11/django-style-database-routers-in-sqlalchemy/ . Zasadniczo można ulepszyć sesję tak, aby wybierała od nadrzędnej lub podrzędnej na podstawie zapytania po zapytaniu. Jednym z potencjalnych problemów z tym podejściem jest to, że jeśli masz jedną transakcję, która wywołuje sześć zapytań, możesz w końcu użyć obu urządzeń podrzędnych w jednym żądaniu… ale tutaj po prostu próbujemy imitować funkcję Django :)
Nieco mniej magiczne podejście, które również bardziej wyraźnie określa zakres użycia, którego użyłem, to dekorator w widoku callables (niezależnie od tego, jak się nazywają w Flask), tak jak to:
@with_slave
def my_view(...):
# ...
with_slave zrobiłby coś takiego, zakładając, że masz skonfigurowaną sesję i niektóre silniki:
master = create_engine("some DB")
slave = create_engine("some other DB")
Session = scoped_session(sessionmaker(bind=master))
def with_slave(fn):
def go(*arg, **kw):
s = Session(bind=slave)
return fn(*arg, **kw)
return go
Pomysł polega na tym, że wywołanie Session(bind=slave)
wywołuje rejestr, aby uzyskać dostęp do rzeczywistego obiektu Session dla bieżącego wątku, tworząc go, jeśli nie istnieje — jednak ponieważ przekazujemy argument, scoped_session zapewni, że sesja, którą tutaj tworzymy, jest zdecydowanie nowa. /P>
Wskazujesz go na "slave" dla wszystkich kolejnych SQL. Następnie, gdy żądanie się zakończy, upewnisz się, że Twoja aplikacja Flask wywołuje Session.remove()
aby wyczyścić rejestr dla tego wątku. Gdy rejestr zostanie ponownie użyty w tym samym wątku, będzie to nowa sesja powiązana z powrotem z „głównym”.
Lub wariant, w którym chcesz użyć „slave” tylko do tego wywołania, jest to „bezpieczniejsze”, ponieważ przywraca istniejące powiązanie z powrotem do sesji:
def with_slave(fn):
def go(*arg, **kw):
s = Session()
oldbind = s.bind
s.bind = slave
try:
return fn(*arg, **kw)
finally:
s.bind = oldbind
return go
Dla każdego z tych dekoratorów możesz odwrócić rzeczy, aby sesja była powiązana z "podrzędną", gdzie dekorator umieszcza ją na "master" dla operacji zapisu. Jeśli chciałbyś w takim przypadku losowego niewolnika, gdyby Flask miał jakieś zdarzenie „rozpoczęcia żądania”, możesz go ustawić w tym momencie.