Flask-SQLAlchemy-会话如何与多个数据库一起使用?

发布于 2021-01-29 17:23:23

我正在开发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'
}

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

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()

我不明白在Flask-SqlAlchemy中使用多个数据库进行会话时会发生什么。

我验证了系统可以通过__bind_key__参数正确地将表绑定到正确的数据库,因此,我可以通过将该数据插入不同数据库中db.session,并在提交时保存所有内容。

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

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

但是我不知道该怎么做。

我还看到了Flask-SQLAlchemy实现,可以简化这些情况的管理:

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

但我不知道如何使用它。

在Flask-SQLAlchemy中,如何管理每个引擎的会话?

关注者
0
被浏览
127
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    Flask-SQLAlchemy使用定制的会话,该会话根据__bind_key__映射类中的给定属性处理绑定路由。实际上,它实际上将该键作为信息添加到创建的表中。换句话说,Flask不会创建多个会话,每个绑定一个会话,而是一个单个会话,该会话根据绑定键路由到正确的可连接对象(引擎/连接)。请注意,香草SQLAlchemy具有开箱即用的类似功能

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

    在会话中使用会话拥有的连接来颠覆并向特定数据库提交提交不是一个好主意。会话是一个整体,并跟踪对象实例的状态,在需要时刷新对数据库的更改等。这意味着会话所处理的事务不仅是数据库事务,而且是会话本身的事务。所有这些都应该提交和回滚。

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

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

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

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

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

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

    还列出了其他不太显式的方法,但是显式比隐式更好。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看