在多租户应用程序中动态设置Flask-SQLAlchemy数据库连接

jst*_*tol 16 python sqlalchemy multi-tenant flask flask-sqlalchemy

我有一个" 多租户 " Flask Web应用程序,它与1个"主"MySQL数据库(用于查找客户端信息)和数十个"客户端"MySQL数据库(都具有相同的模式)连接.

我目前正在尝试使用SQLAlchemyFlask-SQLAlchemy扩展来与数据库连接,但我很难找到一种方法来允许我在我的应用中定义的模型动态地将上下文从一个客户端数据库切换到另一个客户端数据库,取决于客户.

Flask-SQLAlchemy站点上,一个简单的示例如下所示:

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:password@Y.Y.Y.Y/db1'
db = SQLAlchemy(app)

class User(db.Model):
    # Etc.
Run Code Online (Sandbox Code Playgroud)

唯一的问题是,SQLALCHEMY_DATABASE_URI配置是静态完成的.我可能需要在mysql://username:password@Y.Y.Y.Y/db1mysql://username:password@Z.Z.Z.Z/db1(或任何其他任意MySQL URI)之间切换,具体取决于发出请求的客户端.

我发现了一些类似的问题(见下文),但是在使用Flask-SQLAlchemy扩展时,我还没有找到一种干净的方法.

使用sqlalchemy如何基于每个请求动态绑定到数据库引擎

Flask SQLAlchemy设置动态URI

我还看到了一些为处理分片数据库而提供的示例(也应该适用,因为数据库本质上是由客户端逻辑分片),但同样,Flask-SQLAlchemy没有特定的内容.

如果它有意义,我也可以直接使用SQLAlchemy,而不使用Flask-SQLAlchemy扩展.我是SQLAlchemy的新手 - 非常感谢任何帮助!

编辑:能够反映数据库中的表模式将是一个奖励.

Adr*_*laz 0

你可以做这样的事情。仅供参考,这是纯粹的 SQLAlchemy,而不是 Flask-SQLAlchemy。希望您需要它来获取只读内容。您可以找出一些其他必须编写的内容,例如会话/模型上的侦听器

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base

# an Engine, which the Session will use for connection
# resources
some_engine_1 = create_engine('postgresql://scott:tiger@localhost/')
some_engine_2 = create_engine('postgresql://adriel:velazquez@localhost/')

# create a configured "Session" class
Session_1 = sessionmaker(bind=some_engine_1)
Session_2 = sessionmaker(bind=some_engine_2)

# create a Session
session_1 = Session_1()
session_2 = Session_2()

Base = declarative_base()

class ModelBase(Base):
    #different custom queries for each database
    master_query = session_1.query_property()
    client_1_query = session_2.query_property()


class User(ModelBase):
    pass
    #ETC


##Accessing the different databases:
User.master_query.filter(User.id == 1).all()
User.client_1_query.filter(User.id == 1).all()
Run Code Online (Sandbox Code Playgroud)