Подтвердить что ты не робот

Динамическое установление соединения базы данных Flask-SQLAlchemy в приложении с несколькими арендаторами

У меня есть веб-приложение multi-tenant Flask, которое взаимодействует с 1 "основной" базой MySQL (используется для поиска информации о клиенте) и десятками "клиент" базы данных MySQL (все они имеют одну и ту же схему).

В настоящее время я пытаюсь использовать SQLAlchemy вместе с расширением Flask-SQLAlchemy для взаимодействия с базами данных, но я изо всех сил стараюсь найти способ разрешить Модели, которые я определяю в своем приложении, чтобы динамически переключать контекст из одной клиентской базы данных в другую, в зависимости от клиента.

На сайт Flask-SQLAlchemy, простой пример показан в строках:

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

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://username:[email protected]/db1'
db = SQLAlchemy(app)

class User(db.Model):
    # Etc.

Единственная проблема - конфигурация SQLALCHEMY_DATABASE_URI выполняется статически. Мне может потребоваться переключиться между mysql://username:[email protected]/db1 и mysql://username:[email protected]/db1 (или любым другим произвольным URI MySQL), в зависимости от того, какой клиент делает запрос.

Я нашел несколько похожих вопросов (см. ниже), но мне еще предстоит выяснить, как это сделать при использовании расширения Flask-SQLAlchemy.

С sqlalchemy как динамически привязываться к движку базы данных по каждому запросу

Установить флажок SQLAlchemy для динамического URI

Я также видел несколько примеров, которые были предоставлены для обработки оштукатуренных баз данных (что также должно применяться, поскольку базы данных по существу логически привязаны клиентом), но, опять же, ничего особенного для Flask-SQLAlchemy.

Если это имеет смысл, , я также открыт для непосредственного использования SQLAlchemy без расширения Flask-SQLAlchemy. Я новичок в SQLAlchemy - любая помощь будет принята с благодарностью!

Изменить. Возможность отображать схемы таблиц из базы данных будет бонусом.

4b9b3361

Ответ 1

Если вы используете флеш-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. Для получения дополнительной информации вы можете обратиться к официальному документу. Несколько баз данных с привязками

Ответ 2

Вы могли бы сделать что-то вроде этого. FYI это чистая 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:[email protected]/')
some_engine_2 = create_engine('postgresql://adriel:[email protected]/')

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