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

时间:2015-04-15 21:21:23

标签: python flask sqlalchemy flask-sqlalchemy multi-tenant

我有一个“多租户 Flask 网络应用程序,它与1个“主”MySQL数据库(用于查找客户端信息)和几十个“客户端“MySQL数据库(都具有相同的模式)。

我目前正在尝试使用 SQLAlchemy 以及 Flask-SQLAlchemy扩展程序来与数据库进行交互,但我很难找到一种方法来允许我在我的应用中定义的模型 将上下文从一个客户端数据库动态切换到另一个 ,具体取决于客户端。

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

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.

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

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

With sqlalchemy how to dynamically bind to database engine on a per-request basis

Flask SQLAlchemy setup dynamic URI

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

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

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

3 个答案:

答案 0 :(得分:2)

如果您使用flask-sqlalchemy 0.12或更高版本,则BINDS支持此功能。

SQLALCHEMY_DATABASE_URI = 'postgres://localhost/main'
SQLALCHEMY_BINDS = {
'users':        'mysqldb://localhost/users',
'appmeta':      'sqlite:////path/to/appmeta.db'
}

您可以在模型定义中指定连接数据库。

class User(db.Model):
    __bind_key__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)

它将使用mysqldb auto。有关详细信息,请参阅官方文档。 Multiple Databases with Binds

答案 1 :(得分:0)

You could do something like this. FYI this is pure SQLAlchemy, not with Flask-SQLAlchemy. Hopefully you need this for read-only stuff. You can figure out some other stuff to have to write stuff, like even listeners on your session/models

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

答案 2 :(得分:0)

您将需要使用SQLALCHEMY_BINDS方法绑定到多[le客户数据库]。

app.config['SQLALCHEMY_BINDS'] = { 'user1': mysql database', user2: mysqal2database'} 

例如,您还需要在模型中引用诸如“ user1”之类的bind_key名称:

class users(db.Model):
   __bind_key__
   id = db.Column(Integer, primary_key=True)
   name = db.Column(String)

以上这些方法是您应设置的主要SQLALCHEMY_DATABASE_URI之外的方法。虽然您可以在用户登录方法上动态绑定其他数据库。

希望这会有所帮助!