【问题标题】:SQLAlchemy used in Flask, Session management implementationFlask中使用的SQLAlchemy,Session管理实现
【发布时间】:2021-02-04 13:38:17
【问题描述】:

由于模型定义和在 Flask 之外的其他上下文中使用应用程序的数据库部分,我无法使用 Flask-SQLAlchemy,因此我找到了几种管理会话的方法,但我不知道该怎么做。

似乎每个人(包括我)都同意的一件事是,应该在每个请求开始时创建一个新会话,并在处理请求并且准备好将响应发送回客户。


目前,我以这种方式实现了会话管理:

我有一个数据库初始化 python 脚本,它创建引擎 (engine = create_engine(app.config["MYSQL_DATABASE_URI"])) 并定义会话创建者 Session = sessionmaker(bind=engine, expire_on_commit=False)
在另一个文件中,我定义了两个用flask 的before_requestteardown_request 应用程序装饰器装饰的函数。

@app.before_request
def create_db_session():
    g.db_session = Session()

@app.teardown_request
def close_db_session(exception):
    try:
        g.db_session.commit()
    except:
        g.db_session.rollback()
    finally:
        g.db_session.close()

然后我在需要执行查询时使用g.db_sessiong.db_session.query(models.User.user_id).filter_by(username=username)

这是管理会话的正确方法吗?


我还查看了 SQLAlchemy 提出的scoped sessions,这可能是另一种做事方式,但我不确定如何更改我的系统以使用范围会话... 如果我理解得很好,我不会使用g 变量,而是总是引用Session = scoped_session(sessionmaker(bind=engine, expire_on_commit=False)) 声明的Session 定义,并且我不需要在请求到达时显式初始化新会话。 我可以像往常一样使用Session.query(models.User.user_id).filter_by(username=username) 执行我的查询,我只需要在请求结束时删除会话:

@app.teardown_request
def close_db_session(exception):
    Session.commit()
    Session.remove()

我对这个会话管理主题有点迷茫,我需要帮助来了解如何管理会话。上述两种方法有真正的区别吗?

【问题讨论】:

    标签: python flask sqlalchemy


    【解决方案1】:

    您通过flask.g 管理会话的方法在我看来是完全可以接受的。无论我们试图用 SQLAlchemy 做什么,都必须记住基本原则:

    1. 请务必自行清理。在 Web 应用程序运行时,如果您在没有 .close()ing 的情况下生成大量会话,这最终会导致数据库实例的连接溢出。您正在通过调用finally: session.close() 处理此问题
    2. 保持会话独立性。如果各种应用程序上下文(请求、线程等)共享同一个会话实例,那就不好了,因为它不是确定性的。您通过确保每个请求只运行一个会话来做到这一点。

    scoped_session 可以被视为flask.g 的替代品 - 它确保在一个线程内,每次调用 Session() 构造函数都返回相同的对象 - https://docs.sqlalchemy.org/en/13/orm/contextual.html#unitofwork-contextual

    这是一个包含 SQLA 电池的会话管理代码版本。

    到目前为止,如果您使用的是 Flask,它是一个同步框架,我认为您不会对这种设置有任何问题。

    【讨论】:

    • 好的,所以你不建议我切换和使用范围会话?
    • 我是说你管理会话的方式完全没问题。我认为这更像是一个口味问题,您显然可以用Session = scoped_session(sessionmaker(...)) 替换您的会话管理代码,但您必须确保在请求结束时将其删除,所以没有太大的优势。
    猜你喜欢
    • 1970-01-01
    • 2020-06-23
    • 1970-01-01
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 2013-10-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多