#postgresql #flask #sqlalchemy #flask-sqlalchemy #multi-tenant
#postgresql #flask #sqlalchemy #flask-sqlalchemy #многопользовательский
Вопрос:
Проблема
Я создаю веб-приложение, в котором каждый пользователь должен иметь отдельные данные (из-за конфиденциальности), но с точно такими же структурами данных / таблицами.
Оглядываясь вокруг, я думаю, что эта концепция называется многопользовательской? И кажется, что хорошим решением является 1 схема для каждого клиента.
Я думаю, что sqlalchemy 1.1 реализовал некоторую поддержку для этого с
session.connection(execution_options={
"schema_translate_map": {"per_user": "account_one"}})
Однако, похоже, предполагается, что схема и таблицы уже созданы.
Я не уверен, сколько клиентов у меня будет, поэтому мне нужно создать схему и таблицы внутри них «на лету», когда создается учетная запись пользователя.
Решение
То, что я придумал, похоже на небольшой взлом, поэтому я публикую здесь, чтобы узнать, есть ли лучшее решение.
Для создания схем «на лету» я использую
if not engine.dialect.has_schema(engine, user.name):
engine.execute(sqlalchemy.schema.CreateSchema(user.name))
А затем сразу после этого я создаю таблицы, используя
table = TableModel()
table.__table__.schema = user.name
table.__table__.create(db.session.bind)
С помощью TableModel, определенной как
class TableModel(Base):
__tablename__ = 'users'
__table_args__ = {'schema': 'public'}
id = db.Column(
db.Integer,
primary_key=True
)
...
Я не слишком уверен, зачем наследовать от Base vs db.Model — db.Model, похоже, автоматически создает общедоступную таблицу, чего я хочу избежать.
Бонусный вопрос
После создания схемы, если в дальнейшем мне нужно добавить таблицы ко всей схеме — каков наилучший способ управления этим? Справляется ли flask-migrations с этим изначально?
Спасибо!
Комментарии:
1. На данный момент у меня аналогичная проблема, я не такой продвинутый, как вы, но вы можете найти эти две ссылки полезными. В первой статье описывается подход, который, похоже, совпадает с вашим. medium.com/@hamza.senhajirhazi / … / Вторая статья является возможным ответом на ваш бонусный вопрос и касается автоматических миграций в Postgres, здесь на нескольких БД вместо схем: benchling.engineering/ …
2. Я не думаю, что в этой статье medium описывается, как создавать таблицы динамически, они создают таблицы с помощью редактора sql, хотя я не знал о before_request, который, похоже, будет полезен. Спасибо!
3. Вопрос… Использование разных схем полезно в модели арендатора с дифференцированными функциями для разных арендаторов. Если вы говорите, что данные будут точно такими же, почему бы вместо этого не использовать RLS? Это гораздо более простой процесс концептуально и оперативно.
4. @grommit Честно говоря, я не знал о RLS — я изучу это. Просто кажется, что наличие материала в одной таблице делает его менее безопасным? Но я думаю, это не обязательно верно, если оно реализовано правильно.
Ответ №1:
Если кто-нибудь увидит это в будущем, это решение, похоже, в целом работает, однако недавно я столкнулся с проблемой.
Эта строка
table.__table__.schema = user.name
кажется, создает какое-то странное поведение, когда значение user.name кажется, сохраняется в областях заказа приложения, поэтому, если вы переключаете пользователя, таблица от предыдущего пользователя запрашивается неправильно.
Я не совсем уверен, почему это происходит, и все еще изучаю, как это исправить.