Flask-SQLAlchemy 和 SQLAlchemy

Posted

技术标签:

【中文标题】Flask-SQLAlchemy 和 SQLAlchemy【英文标题】:Flask-SQLAlchemy and SQLAlchemy 【发布时间】:2015-03-25 22:53:53 【问题描述】:

我正在建立一个小型网站,并且我已经在 SQLAlchemy 中拥有所有我的模型。该网站将发布一些离线计算的信息。只有结果会发布到精简的数据库,即它包含结果,而不是原始数据,但网站需要查询结果。

我将使用 Flask,因为我的模型已经使用 Python 驱动(并且通过 SWIG 在 C++ 中进行了一些繁重的工作)并且我不想使用 Django。

现在,在我确定之前已经问过这个问题,通常没有太多理由的口头禅是“使用 Flask-SQLAlchemy”。问题是为什么?

如果我自己编写一些会话处理,为什么我必须在 Flask-SQLAlchemy 中重新定义我的数据库的附加层。除了必须在我的 Flask 应用程序中的某个地方编写一些类似 here 的代码:

@app.before_request
def before_request():
  g.db = connect_db()

@app.teardown_request
def teardown_request(exception):
  db = getattr(g, 'db', None)
  if db is not None:
    db.close()

我还需要担心什么? SQLAlchemy 甚至默认为我做连接池。

【问题讨论】:

【参考方案1】:

实际上,您正在使用Flask 构建一个Web 应用程序,它通过sqlalchemy 执行与数据库相关的各种工作。因此,当您使用应用程序处理的多个请求处理数据库 会话 时,您必须确定,您正在谨慎地创建和关闭会话。

如果您阅读 SQLAlchemy docs,他们建议将会话的生命周期与访问和/或操作数据库数据的函数和对象分开并保持在外部。这将极大地帮助实现可预测且一致的事务范围。

Web 应用程序是最简单的情况,因为这样的应用程序已经围绕一个单一的、一致的范围构建——这就是 request,它表示来自浏览器的传入请求,处理该请求以制定响应,最后将该响应返回给客户端。将 Web 应用程序与 Session 集成就是将Session 的范围链接到请求的范围的简单任务。 Session 可以在请求开始时建立,或者使用惰性初始化模式在需要时立即建立。然后请求继续进行,其中应用程序逻辑可以以与访问实际请求对象的方式相关联的方式访问当前会话的某个系统到位。随着请求结束,Session 也被拆除,通常是通过使用 Web 框架提供的事件挂钩。 Session 使用的事务也可以在此时提交,或者应用程序可以选择显式提交模式,只提交那些有保证的请求,但仍然总是在最后无条件地拆除Session

用外行的话,我的意思是说

SQLAlchemy 中提到了上述操作,因为 Web 应用程序中的会话应该是作用域,这意味着每个请求处理程序都会创建和销毁自己的会话。

这是必要的,因为 Web 服务器可以是多线程的,因此可能会同时处理多个请求,每个请求使用不同的数据库会话。

这意味着如果您将 SqlAlchemyFlask 一起使用,您必须手动处理会话,例如创建 scoped session,并在每个请求中谨慎删除它们,否则您可能陷入困境,这给您的 Web 应用程序增加了额外的复杂性。

但是,Flask-SqlAlchemyFlask 应用程序的 sqlalchemy 库的扩展)提供了基础设施,以协助将 Session 的生命周期与每个 Session 的生命周期对齐网络请求。其实你也可以在SqlAlchmeydocs中找到,他们也推荐使用Flask

Flask-SQLAlchemy 为每个请求创建一个全新的scoped session。如果你进一步挖掘它,你会发现在这里,它还在app.teardown_appcontext(对于 Flask >=0.9)、app.teardown_request(对于 Flask 0.7-0.8)、app.after_request(对于 Flask db.session.remove()的地方。

【讨论】:

【参考方案2】:

您在问题中输入的代码实际上对于 Sqlalchemy 集成无效是 Flask。我知道这只是一个例子,但以防万一。

对于 Sqlalchemy 集成,您需要做的就是确保在请求结束时通过以下方式清除当前的 DbSession

@app.teardown_appcontext
def shutdown_session(exception=None):
    DbSession.remove()

其中 DbSession 是 scoped session。

Here is documentation 用于您不想使用 Flask-Sqlalchemy 包的情况。

【讨论】:

以上是关于Flask-SQLAlchemy 和 SQLAlchemy的主要内容,如果未能解决你的问题,请参考以下文章

《Flask web开发》笔记4:数据库

Flask-SQLAlchemy:用户角色模型和关系

Flask-Sqlalchemy 和水平缩放和范围会话

FLASK-SQLALCHEMY如何使用or和and条件进行组合查询

Flask-SQLAlchemy 和 Gevent 没有关闭 mysql 连接

flask-sqlalchemy:数据未更新[重复]