我们使用sqlAlchemy和postgres托管一个多租户应用程序。我正在考虑从每个租户的单独数据库转移到具有多个架构的单个数据库。 sqlAlchemy是否支持本机?我基本上只是希望每一个出来的查询以预定的模式为前缀
select * from client1.users
而不是只是
select * from users
请注意,我想在特定请求/一组请求中切换所有表的模式,而不仅仅是单个表。
那么有几种方法可以解决这个问题,这取决于你的应用程序的结构。这是最基本的方法:
Meta = MetaData(schema="client1")
如果你的应用程序运行的方式是整个应用程序中的一个“客户端”,你就完成了。
但是这可能是错误的,MetaData的每个表都是在该模式上。如果您想要一个应用程序同时支持多个客户端(通常是“多租户”的意思),那么这将是笨重的,因为您需要创建一个MetaData的副本并且将每个客户端的所有映射都复制出去。如果你真的想要这个方法,那么你可以使用一个特定的映射类来访问每个客户端,如果你真的想要这样做,
client1_foo = Client1Foo()
在这种情况下,您将使用http://www.sqlalchemy.org/trac/wiki/UsageRecipes/EntityName中的“实体名称”配方与soMetable.toMetadata()一起使用(参见http://docs.sqlalchemy.org/en/latest/core/schema.html?highlight=metadata#sqlalchemy.schema.Table.tometadata)。
所以让我们说,它真正有效的方式是应用程序中的多个客户端,但每个线程只能一个。实际上,在Postgresql中最简单的方法是在开始使用连接时设置搜索路径:
# start request # new session sess = Session() # set the search path sess.execute("SET search_path TO client1") # do stuff with session # close it. if you're using connection pooling,the # search path is still set up there,so you might want to # revert it first sess.close()
最终的方法是使用@compiles扩展来覆盖编译器,以将“schema”名称粘贴在语句内。这是可行的,但是会很棘手,因为没有一个一致的钩子,无处不在“表”被生成。你最好的选择是设置每个请求的搜索路径。