在 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_flushafter_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 中填充相关表的主要内容,如果未能解决你的问题,请参考以下文章

mysql八:ORM框架SQLAlchemy

在SQLAlchemy ORM中动态变更表名

flask 中orm关系映射 sqlalchemy的查询

ORM框架SQLAlchemy的使用

Sqlalchemy

SqlAlchemy 用 ORM 截断表