Problem
I'm building a web app, where each user needs to have segregated data (due to confidentiality), but with exactly the same data structures/tables.
Looking around I think this concept is called multi-tenants? And it seems as though a good solution is 1 schema per tenant.
I think sqlalchemy 1.1 implemented some support for this with
session.connection(execution_options={
"schema_translate_map": {"per_user": "account_one"}})
However this seems to assume the schema and tables are already created.
I'm not sure how many tenants I'm going to have, so I need to create the schema, and the tables within them, on the fly, when the user's account is created.
Solution
What I've come up with feels like a bit of a hack, which is why I'm posting here to see if there's a better solution.
To create schemas on the fly I'm using
if not engine.dialect.has_schema(engine, user.name):
engine.execute(sqlalchemy.schema.CreateSchema(user.name))
And then directly afterwards I'm creating the tables using
table = TableModel()
table.__table__.schema = user.name
table.__table__.create(db.session.bind)
With TableModel defined as
class TableModel(Base):
__tablename__ = 'users'
__table_args__ = {'schema': 'public'}
id = db.Column(
db.Integer,
primary_key=True
)
...
I'm not too sure why to inherit from Base vs db.Model - db.Model seems to automatically create the table in public, which I want to avoid.
Bonus question
Once the schema are created, if, down the line, I need to add tables to all the schema - what's the best way to manage that? Does flask-migrations natively handle that?
Thanks!