在 flask-sqlalchemy 中使用具有相同模型的多个数据库

Posted

技术标签:

【中文标题】在 flask-sqlalchemy 中使用具有相同模型的多个数据库【英文标题】:Using multiple database with same model in flask-sqlalchemy 【发布时间】:2018-01-22 08:16:13 【问题描述】:

所以我有多个数据库。 DB_USDB_UK。它们具有完全相同的结构,但它们保存不同国家/地区的数据。我有一个带有 flask_restful 的 api。端点接受一个国家来检索这个特定国家的数据。

我的问题是我不知道如何根据请求选择数据库。我已经阅读了 bind 方法,但是您必须为每个模型指定一个 __bind_key,并且我的所有模型都在两个数据库中。

我尝试在@before_request 中初始化数据库,但是在处理完第一个请求后,您无法调用init_db 方法(或任何设置方法)。

这是一个特殊情况,因为数据库是相同的,所以将它放在同一个数据库中似乎是有意义的,但它是更大系统的一部分,需要这样。

如何根据每个请求选择数据库?

【问题讨论】:

【参考方案1】:

我遇到了同样的问题。我在这里描述过Using multiple POSTGRES databases and schemas with the same Flask-SQLAlchemy model

您的案例稍微容易一些,因为您不必处理架构差异。 您可以按照 stamaimer 的建议进行操作,但问题是为每个国家/地区创建了新的用户模型(如果您有超过 2 个,它就会变得混乱)。

为了解决这个问题,我停止使用 flask-sqlAlchemy db 实例化方法,让内容提供者 init 方法处理要选择的 db:

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

Session = sessionmaker()

class ContentProvider():

    db = None
    connection = None
    session = None

    def __init__(self, center):
        if center == UK:
            self.db = create_engine('sqlite://UK', echo=True, pool_threadlocal=True)
            self.connection = self.db.connect()
        elif center == US:
            self.db = create_engine('sqlite://US', echo=True, pool_threadlocal=True)
            self.connection = self.db.connect()
        self.session = Session(bind=self.connection)

    def index(country):
        user = models[country]["User"](username=country + str(time.time()))
        self.session.add(user)
        self.session.commit()
        return country, "added"

【讨论】:

【参考方案2】:

也许您可以定义一些基本数据模型并为单独的数据库继承它们。例如:

class User(db.Model):

    __abstract__ = 1

    # fields define

class UserUK(User):

    __bind_key__ = 'uk'

class UserUS(User):

    __bind_key__ = 'us'

您可以创建一个model = "uk": "User": UserUK, "us": "User": UserUS 的字典,以便从请求中按国家/地区选择合适的型号。例如:model[country]["User"]

完整演示:

import time
from flask import Flask
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////path/2/default.db"
app.config["SQLALCHEMY_BINDS"] = "uk": "sqlite:////path/2/uk.db", "us": "sqlite:////path/2/us.db"

db = SQLAlchemy(app)


class UserBase(db.Model):

    __abstract__ = 1

    id = db.Column(db.Integer, primary_key=1)

    username = db.Column(db.String(16))


class UserUK(UserBase):

    __bind_key__ = "uk"


class UserUS(UserBase):

    __bind_key__ = "us"


models = "uk": "User": UserUK, "us": "User": UserUS


@app.route("/<country>")
def index(country):

    user = models[country]["User"](username=country + str(time.time()))

    db.session.add(user)

    db.session.commit()

    return country, "added"


if __name__ == "__main__":

    app.run(debug=1)

【讨论】:

以上是关于在 flask-sqlalchemy 中使用具有相同模型的多个数据库的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Flask-SQLAlchemy 使用 csv 填充具有外键的模型?

Flask-Sqlalchemy 使用 postgres 创建视图

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

如何在 Celery 任务中使用 Flask-SQLAlchemy

使用 Flask-SQLAlchemy 在 Alembic 自动生成迁移中未检测到任何变化

在 Flask-sqlalchemy 和 Postgresql 中使用 JSON 类型