Python 如果要使用SQLAlchemy将多个数据库连接到各种应用程序,组织模型和连接的好方法是什么? 背景:
这就是我面临的情况,到目前为止,我目前的解决方案似乎相当笨拙。我想改进一下。现在:Python 如果要使用SQLAlchemy将多个数据库连接到各种应用程序,组织模型和连接的好方法是什么? 背景:,python,design-patterns,sqlalchemy,tornado,pyramid,Python,Design Patterns,Sqlalchemy,Tornado,Pyramid,这就是我面临的情况,到目前为止,我目前的解决方案似乎相当笨拙。我想改进一下。现在: 我在金字塔应用程序的主要功能中设置与每个数据库的连接: “ASession”和“BSession”只是在/models/init.py中全局定义的作用域会话 我这样定义模型基类。例如: 不知怎么的,这感觉已经不是很干净了。但是现在这个模型应该从不同的应用程序访问,我还需要在该应用程序中再次定义引擎和连接。这感觉非常多余 问题摘要: 假设有两个不同的数据库: A和B 还假设您希望A和B可以从使用相同模型
- 我在金字塔应用程序的主要功能中设置与每个数据库的连接:
- “ASession”和“BSession”只是在/models/init.py中全局定义的作用域会话
- 我这样定义模型基类。例如:
社区将如何处理这一问题?至少在周五下午,我不愿意为自己找到这些问题的答案。我已经这样做了。下面我的建议是我喜欢这样做,但不是唯一的方法。我将抛弃作用域会话和事务管理器,创建显式会话管理对象,使用请求生命周期回调处理会话的创建、关闭、提交或回滚。基本上,作用域会话是一种通过为该执行线程获取相同项来模拟全局会话的方法。在金字塔中实现这一点的另一种方法是将东西附加到注册表和请求中,因为它们无处不在。您将共享组件附加到注册表(ZCA),并将每个请求对象附加到请求 当您有多个会话时,我发现如果这些会话是由为该引擎打包所有内容的组件处理的,那么就更容易对它们进行推理和跟踪。对于您描述的这种情况,我制作了两个不同的DB引擎组件,它们在启动时创建,连接到注册表,并有一个获取新会话的方法。如果您正确地创建了这些组件,它们应该可以在任何应用程序中使用,无论是Pyramid、Tornado还是您的测试脚本。您只需确保它有一个构造函数,它以某种合理的方式传递设置以设置引擎,无论是设置dict还是kwargs。然后,我让我的数据模型生活在他们自己的python包中,让家族中的任何应用程序都可以很容易地导入模型、实例化引擎组件并进城。请注意,如果您喜欢使用ZCA注册表(我喜欢它,它是一个很棒的DI系统),没有什么可以阻止您在非金字塔应用程序中使用它,您只需在服务器启动代码中手动设置它 具体来说,在Pyramid中,我创建了一个自定义请求类,并使用具体化装饰器允许其他Pyramid代码获取该请求的会话。request类具有附加的生命周期结束回调以关闭会话,并执行回滚或提交。还有更多的样板文件,但对我来说更简洁,因为我可以很容易地跟踪在代码中何时何地以及会话管理发生的时间。这也是一种很好的测试方法
也就是说,SQLAlchemy/Pyramid领域中有很多聪明的人对范围会话和事务管理器发誓,所以还有其他有效的方法。希望这会有所帮助。可能很难在模型包中完全包含会话类的创建,例如。引擎可能由模型包提供,但另一方面,模型不应该关心它所针对的是什么DB。总之,引擎和会话是特定于应用程序的。谢谢你,Ilja。这个链接提供了大量信息。这让我意识到,我对龙卷风一无所知。那么,在Tornado中使用SQLAlchem连接数据库的好方法是什么呢?这太棒了!一般来说,这就是我所想的。这种模式称为“网关”模式吗?我之所以这样问,是因为如果这个术语是已知的,那么就更容易搜索更多关于这个的信息。我想找到一些Python中的示例实现代码。
def main(global_config, **settings):
a_engine = engine_from_config(settings, 'A.')
b_engine = engine_from_config(settings, 'B.')
ASession.configure(bind=a_engine)
BSession.configure(bind=b_engine)
ASession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
ABase = declarative_base()
class user(ABase):
id = Column(Integer, primary_key=True)
name = Column(String)