在 SqlAlchemy ORM 中填充相关表
Posted
技术标签:
【中文标题】在 SqlAlchemy ORM 中填充相关表【英文标题】:Populating related table in SqlAlchemy ORM 【发布时间】:2017-10-05 21:11:53 【问题描述】:所以我有两个表处于一对多关系中。当我创建Table1
的新行时,我想用相关行填充Table2
。然而,这个人口实际上涉及计算Table2
行,使用其他相关表中的数据。
使用 ORM 层有什么好的方法?也就是说,假设 Table1
映射是通过 ORM 创建的,我应该在哪里/如何调用代码来填充 Table2
?
我考虑过使用after_insert
钩子,但我想有一个会话传递给人口方法。
谢谢。
【问题讨论】:
你尝试了什么? 真的很难想。映射__init__
方法已失效,因为它在对象处于会话/事务中之前。我研究了 sqlalchemy 的各种钩子。 after_insert
为您提供连接,而不是会话。我的人口代码需要一个会话。是否有等效的钩子,但对于会话?
【参考方案1】:
您可以使用before_flush
或after_flush
hook,它提供了session
。然后检查session.new
对象以获取新创建的模型(提示:使用isinstance(object, ModelClass)
)并在此处完成您的工作。
事实上,SQLAlchemy recommends before_flush
用于一般刷新更改。
Mapper 级别的刷新事件只允许非常有限的操作,仅限于被操作的行的本地属性,以及允许在给定的连接上发出任何 SQL。请完整阅读 Mapper-level Events 中的注释,了解使用这些方法的指南;通常,对于一般的刷新更改,应首选 SessionEvents.before_flush() 方法。
【讨论】:
我想过类似的事情,但是对所有创建的对象进行isinstance
检查,更不用说刷新事件了,似乎效率极低。我希望这不是唯一的方法。在我看来,我想做的应该是一个共同的模式;这真的是通常的做法吗?
这是由 SqlAlchemy 推荐的。从这个孤立的案例来看,它可能看起来“效率低下”,但在更高的层次上,未来可能需要为其他模型定制处理程序。我实现了一个包罗万象的before_flush
并重新路由到各个模型类的特定处理程序(与每个类的多个before_flush
相比)。根据我的经验,isinstance
不太可能是您的瓶颈。
好的。那么其他会话事件呢,比如“pending_to_persistant”?这是一个后刷新事件,是否意味着它不能回滚?
所以after_flush
在提交之前,所以我想如果我的填充代码失败,我可以回滚原始插入。
其实“before_flush”不起作用:对象还没有id。【参考方案2】:
在#sqlalchemy IRC 中询问后,有人指出这可以在before_flush
事件侦听器中使用 ORM 级关系来完成。
解释了当你通过关系添加映射时,刷新时会自动填充外键,并由ORM生成相应的插入语句。
【讨论】:
以上是关于在 SqlAlchemy ORM 中填充相关表的主要内容,如果未能解决你的问题,请参考以下文章