30 lines
1.3 KiB
Python
30 lines
1.3 KiB
Python
"""
|
|
app/tenancy/routing.py
|
|
----------------------
|
|
RoutingSession — the per-request tenant-aware SQLAlchemy session.
|
|
|
|
Subclasses Flask-SQLAlchemy's own Session so that all existing behaviour
|
|
(default bind, __bind_key__ resolution) is preserved. The ONLY change: when a
|
|
tenant engine has been selected for the current request (g.tenant_engine, set
|
|
by the resolver middleware), every query binds to that engine instead.
|
|
|
|
When no tenant engine is present — multi-tenancy disabled, an exempt path, a
|
|
CLI invocation, or any non-request context — this falls through to the normal
|
|
Flask-SQLAlchemy behaviour, i.e. the app's configured default database. This
|
|
makes the routing layer completely inert until a tenant is actually resolved,
|
|
so the existing single-tenant deployment is unaffected.
|
|
"""
|
|
|
|
from flask import g, has_app_context
|
|
from flask_sqlalchemy.session import Session as _FlaskSQLAlchemySession
|
|
|
|
|
|
class RoutingSession(_FlaskSQLAlchemySession):
|
|
def get_bind(self, mapper=None, clause=None, bind=None, **kwargs):
|
|
# Respect an explicitly supplied bind (engine-targeted operations).
|
|
if bind is None and has_app_context():
|
|
tenant_engine = g.get('tenant_engine', None)
|
|
if tenant_engine is not None:
|
|
return tenant_engine
|
|
return super().get_bind(mapper=mapper, clause=clause, bind=bind, **kwargs)
|