2016-04-26 97 views
2

我有一個flask webapp,用戶將能夠連接到自己的MySQL數據庫和查詢自己的表燒瓶SQLAlchemy的 - 在飛行連接到多個數據庫

什麼是創建多個連接的最佳方式(以不同數據庫)使用flask-sqlalchemy。它似乎需要與scoped_sessionsessionmaker完成,但似乎不能包圍我的頭。

此外,問題的第二部分,一旦我創建一個連接到一個用戶的MySQL數據庫,我如何堅持連接跨請求?

目前,我把連接字符串的燒瓶會話變量中的每個用戶,並在每個新的請求,我創建了發動機和連接,這樣

engine = create_engine(connection_string, convert_unicode=True) 
conn = engine.connect() 
db_session = Session(bind=conn) # Session - i create it globally on the __init__ like this Session = scoped_session(sessionmaker()) and import it in the view 

## Query using the db_session 

這似乎超級浪費創建發動機和與每個請求連接 - 無法連接跨請求持續?

+1

用你需要的任何數據替換這個問題中的「rserve」(http://stackoverflow.com/questions/28423069/how-can-a-unique-rserve-connection-be-stored-per-session) ,在這種情況下是一個SQLAlchemy引擎。 – davidism

+2

您不會使用Flask-SQLAlchemy,因爲這對於提前配置管理自己的數據庫非常方便。 – davidism

回答

3

單個數據庫

該引擎允許您使用連接池。默認情況下,它將持續連接請求。基本用法(不象​​scoped_sessionsessionmaker花哨的東西)是這樣的:

engine = create_engine(...) 

@app.route(...) 
def foo(): 
    session = Session(bind=engine) 
    try: 
     session.query(...) 
     session.commit() 
    finally: 
     session.close() 
    return "" 

在此之上,你可以添加scoped_sessionsessionmaker

engine = create_engine(...) 
Session = sessionmaker(bind=engine) 
session = scoped_session(Session, scopefunc=...) 

@app.route(...) 
def foo(): 
    try: 
     session.query(...) 
     session.commit() 
    finally: 
     session.close() 
    return "" 

flask-sqlalchemy讓您的生活更輕鬆所有其中:

db = SQLAlchemy(app) 

@app.route(...) 
def foo(): 
    db.session.query(...) 
    db.session.commit() 
    return "" 

多個數據庫

當您添加 scoped_sessionsessionmaker

engine1 = create_engine(...) 
engine2 = create_engine(...) 

@app.route(...) 
def foo(): 
    session = Session(bind=choose_engine_for_user()) 
    try: 
     session.query(...) 
     session.commit() 
    finally: 
     session.close() 
    return "" 

您可以輕鬆地這個概念擴展到多個數據庫

engine1 = create_engine(...) 
engine2 = create_engine(...) 
Session1 = sessionmaker(bind=engine1) 
Session2 = sessionmaker(bind=engine2) 
session1 = scoped_session(Session1, scopefunc=...) 
session2 = scoped_session(Session2, scopefunc=...) 

@app.route(...) 
def foo(): 
    session = choose_session_for_user() 
    try: 
     session.query(...) 
     session.commit() 
    finally: 
     session.close() 
    return "" 

這得到,當你有多個數據庫有點煩,在這種情況下,你應該可能寫一個註冊表類以跟蹤所有引擎和會話:

class SessionRegistry(object): 
    _registry = {} 

    def get(self, url, **kwargs): 
     if url not in self._registry: 
      engine = create_engine(url, **kwargs) 
      Session = session_maker(bind=engine) 
      session = scoped_session(Session, scopefunc=...) 
      self._registry[url] = session 
     return self._registry[url] 

registry = SessionRegistry() 

@app.route(...) 
def foo(): 
    session = registry.get(...) 
    try: 
     session.query(...) 
     session.commit() 
    finally: 
     session.close() 
    return "" 

您需要在其上添加某種LRU,以便沒有無限制的引擎創建。

flask-sqlalchemy支持有限形式的多個數據庫,其中每個模型都連接到不同的數據庫。如果這適用於您,則文檔爲here

+0

感謝Univerio。問題是我沒有爲應用程序本身設置多個數據庫 - 它的應用程序用戶需要創建與其數據庫的連接來查詢他們的表。請你詳細說一下「註冊表類以跟蹤所有引擎和會話」 –

+1

@sarul請參閱編輯。如果您需要在應用程序的生命週期中連接到任意數量的數據庫,那麼您需要在註冊表之上添加某種LRU來檢查內存泄漏。 – univerio

+0

完美。感謝Univerio的詳細回覆。 –