#sqlalchemy
#sqlalchemy
Вопрос:
Мы пытаемся настроить службу SaaS, которая поддерживает многопользовательскую работу в общей базе данных и схеме. Мы планируем иметь столбец tenant_id во всех наших таблицах. что я хотел бы сделать, так это то, что разработчику не нужно писать какой-либо дополнительный код, чтобы мои запросы автоматически фильтровали все задействованные таблицы по этому идентификатору клиента. Есть ли прозрачный способ добиться этого в SQL Alchemy?
Я нашел, как вы можете переопределить объект запроса по умолчанию:
self.session = sessionmaker(bind=engine, query_cls=TenantLimitingQuery)
Но внутри этого TenantLimitingQuery как можно применить его ко всем задействованным таблицам?
class TenantLimitingQuery(Query):
def get(self, ident):
#apply filter here
В моих таблицах есть один и тот же столбец для идентификации арендатора с именем tenant_id, поэтому в этой функции get мне нужно выполнить фильтрацию по tenant_id=current_tenant_id
Ответ №1:
Это изложено в вики-рецептах использования, воспроизведенных здесь:
from sqlalchemy.orm.query import Query
class LimitingQuery(Query):
def get(self, ident):
# override get() so that the flag is always checked in the
# DB as opposed to pulling from the identity map. - this is optional.
return Query.get(self.populate_existing(), ident)
def __iter__(self):
return Query.__iter__(self.private())
def from_self(self, *ent):
# override from_self() to automatically apply
# the criterion too. this works with count() and
# others.
return Query.from_self(self.private(), *ent)
def private(self):
mzero = self._mapper_zero()
if mzero is not None:
crit = mzero.class_.public == True
return self.enable_assertions(False).filter(crit)
else:
return self
Идея состоит в том, чтобы применять фильтр по требованию, когда объект запроса повторяется.
Если вы хотите, чтобы фильтр также применялся к связям, вам нужно будет использовать этот рецепт.
Комментарии:
1. Эту суть можно использовать для фильтров по умолчанию, специфичных для конкретной модели gist.github.com/aklos/6c4afd656d1c8fdf1dad