Flask-SQLAlchemy-动态连接到多个数据库

jet*_*com 4 mysql session sqlalchemy flask flask-sqlalchemy

我有一个flask webapp用户可以连接到自己的mysql数据库并查询自己的表的地方

使用flask-sqlalchemy创建到不同数据库的多个连接的最佳方法是什么。似乎需要处理scoped_sessionsessionmaker但似乎无法解决。

同样是问题的第二部分,一旦我为其中一个用户创建了与mysql db的连接,我如何在请求之间保持连接?

当前,我将每个用户的连接字符串放在flask会话变量上,并在每个新请求下,依次创建引擎和连接

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
Run Code Online (Sandbox Code Playgroud)

这对于创建引擎和与每个请求的连接来说非常浪费,无法在请求之间保持连接吗?

uni*_*rio 6

一个数据库

该引擎使您可以使用连接池。默认情况下,它将在请求之间保持连接。基本用法(没有类似scoped_session或的奇特用法sessionmaker)如下:

engine = create_engine(...)

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

在此之上,您可以添加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 ""
Run Code Online (Sandbox Code Playgroud)

flask-sqlalchemy 提供以下所有功能,使您的生活更轻松:

db = SQLAlchemy(app)

@app.route(...)
def foo():
    db.session.query(...)
    db.session.commit()
    return ""
Run Code Online (Sandbox Code Playgroud)

多个数据库

您可以轻松地将此概念扩展到多个数据库:

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 ""
Run Code Online (Sandbox Code Playgroud)

当您添加scoped_sessionsessionmaker

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 ""
Run Code Online (Sandbox Code Playgroud)

当您有许多数据库时,这会有些烦人,在这种情况下,您可能应该编写一个注册表类来跟踪所有引擎和会话:

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 ""
Run Code Online (Sandbox Code Playgroud)

您需要在其之上添加某种LRU,以便不会无限创建引擎。

flask-sqlalchemy支持有限形式的多个数据库,其中每个模型都连接到不同的数据库。如果您喜欢,请参阅此处的文档。

  • @sarul参见编辑。如果您需要在应用程序的生命周期内连接到任意数据库(数量不限),则需要在注册表顶部添加某种LRU,以检查内存泄漏情况。 (2认同)