当前位置: 首页 > 知识库问答 >
问题:

Flask-SQLAlChemy-会话如何与多个数据库一起工作?

赵昊阳
2023-03-14

我正在处理一个Flask项目,我正在使用Flask SQLAlchemy。
我需要处理多个已经存在的数据库。
我创建了“app”对象和SQLAlchemy对象:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)
db = SQLAlchemy(app)

在配置中,我设置了默认连接和附加绑定:

SQLALCHEMY_DATABASE_URI = 'postgresql://pg_user:pg_pwd@pg_server/pg_db'
SQLALCHEMY_BINDS = {
    'oracle_bind': 'oracle://oracle_user:oracle_pwd@oracle_server/oracle_schema',
    'mssql_bind': 'mssql+pyodbc://msssql_user:mssql_pwd@mssql_server/mssql_schema?driver=FreeTDS'
}

然后,我使用声明性系统创建了表模型,并在需要时设置\uu bind\u key\uu参数以指示表位于哪个数据库中。
例如:

class MyTable(db.Model):
    __bind_key__ = 'mssql_bind'
    __tablename__ = 'my_table'
    
    id = db.Column(db.Integer, nullable=False, primary_key=True)
    val = db.Column(db.String(50), nullable=False)

通过这种方式,当我在正确的数据库上进行查询时,一切都正常工作。

阅读SQLAlchemy文档和Flask SQLAlchemy文档,我了解这些内容(我将它们写下来以检查我是否正确理解):

  • 您可以通过会话处理事务。
  • 在SQLAlChemy中,您可以将会话与特定的引擎绑定。
  • Flask-SQLAlChemy在请求开始时自动创建会话(scoped_session),并在请求结束时销毁它

所以我可以这样做:

record = MyTable(1, 'some text')
db.session.add(record)
db.session.commit()

我无法理解在炼金术中使用多个数据库时会发生什么。

我通过\uu bind\u key\uu参数验证了系统能够在正确的数据库中正确绑定表,因此,我可以通过db.session在不同的数据库上插入数据,并且在提交时,所有内容都被保存。

但是,我无法理解SQLAlchemy是否创建了多个会话(每个引擎一个)或if以不同的方式管理事物。
在这两种情况下,如何引用特定数据库的会话/事务?
如果使用db.session.commit()系统会对所有涉及的数据库进行提交,但是如果我只想对单个数据库进行提交,我该怎么做呢?
我会这样做:

db.session('mssql_bind').commit()

但我不知道如何做到这一点。

我还看到了一个Alchemy实现,它应该可以简化这些情况的管理:

问题:https://github.com/mitsuhiko/flask-sqlalchemy/issues/107
实施:https://github.com/mitsuhiko/flask-sqlalchemy/pull/249

但我不知道如何使用它。

在SQLAlchemy中,如何专门为每个引擎管理会话?

共有1个答案

曾成天
2023-03-14

Flask SQLAlchemy使用自定义会话,该会话根据映射类中给定的\uu bind\u key\uu属性处理绑定路由。在引擎盖下,它实际上将该键作为信息添加到创建的表中。换句话说,Flask不会创建多个会话(每个绑定一个会话),而是创建一个根据绑定键路由到正确可连接(引擎/连接)的会话。请注意,vanilla SQLAlchemy具有类似的现成功能。

在这两种情况下,如何引用特定数据库的会话/事务?如果我使用db.session.commit()系统会对所有涉及的数据库进行提交,但是如果我只想对单个数据库进行提交,该怎么做呢?

在会话中期使用会话所拥有的连接来破坏和发布对特定数据库的提交可能不是一个好主意。会话是一个整体,跟踪对象实例的状态,在需要时刷新对数据库的更改等。这意味着会话处理的事务不仅是数据库事务,而且也是会话自己的事务。所有这些都应该作为一个整体提交和回滚。

另一方面,您可以创建新的SQLAlchemy(或Flask SQLAlchemy)会话,这些会话可能在以下绑定之一中加入正在进行的事务:

session = db.create_scoped_session(
    options=dict(bind=db.get_engine(app, 'oracle_bind'),
                 binds={}))

这就是pull请求的内容。它允许使用现有事务连接作为新会话的绑定。这在测试中非常有用,从pull请求的基本原理可以看出。这样,您就可以拥有一个“主”事务,例如可以回滚测试中完成的所有操作。

请注意,如果存在bind_key,则Signallingsession始终会查询db.get_engine()方法。这意味着示例会话无法在没有绑定键的情况下查询表,而绑定键在oracle DB上不存在,但仍适用于具有mssql_bind键的表。

另一方面,您链接到的问题确实列出了向特定绑定发布SQL的方法:

rows = db.session.execute(query, params,
                          bind=db.get_engine(app, 'oracle_bind'))

也列出了其他不太显式的方法,但显式方法优于隐式方法。

 类似资料:
  • 问题内容: 我有一个使用Flask-SQLAlchemy的Flask应用程序,我正在尝试将其配置为使用Flask-Restless软件包使用多个数据库。 根据文档,配置模型以使用多个数据库似乎非常简单。 但是,它似乎不适用于我。 我创建我的应用程序并初始化数据库,如下所示: 然后定义包括在内的模型,这些模型应该告诉SQLAlchemy它需要使用哪个数据库: 然后我像这样启动Flask-Restle

  • 问题内容: 我有一个简单的用户模型,定义如下: 当我创建一个新的User对象时,我的字段将设置为当前时间。我想要做的是使它每当我将更改保存到User对象时,我的字段就会自动设置为当前时间。 我已经仔细阅读过文档,但是对于我一生来说,我似乎找不到任何对此的引用。我是SQLAlchemy的新手,所以我确实没有任何经验可以借鉴。 问题答案: 只需在列字段中添加或参数: 我更喜欢列名称。;) 有关列插入/

  • 问题内容: 我试图在 Flask-SQLAlchemy中 建立多对多关系,但似乎我不知道如何填写 “多对多标识符数据库” 。您能帮我了解我在做什么错以及应该怎么看吗? 然后是我的标识符数据库: 到目前为止,当我尝试将数据插入数据库时​​,看起来像这样。 现在我的问题是,由于我真的无法创建“ student_identifier”对象,如何将其添加到多对多数据库?如果可以的话,它可能看起来像这样:

  • 问题内容: 遵循我们在如何在MySQL中关闭sqlalchemy连接中的注释之后,我正在检查SQLAlchemy创建到数据库中的连接,如果不退出Python,我将无法关闭它们。 如果我在python控制台中运行此代码,它将保持会话打开状态,直到我退出python为止: 我发现要关闭它的唯一解决方法是在最后调用。 根据我上面给出的链接中的评论,我的问题现在是: 为什么需要关闭会议? 还不够吗 问题答

  • 问题内容: 2 能否从2个不同的mongdb数据库服务器中检索数据? 问题答案: 更新资料 现在可以连接到远程/多个数据库: mongodb url 在哪里,例如(带有数据库名称) 目前,这样做有一个缺点:没有Oplog 旧答案 目前,这是不可能的。每个流星应用程序都绑定到一个数据库。 您可以通过几种方法解决此问题,但其价值可能会更复杂: 一种选择-使用单独的Meteor应用 在另一个流星应用程序

  • 我正在尝试用库制作一个程序。 当我尝试访问一个头函数时,我得到了一个错误。 main.cpp: 测试h: 我是初学者,所以我真的不知道如何修复它或它的可能性。