我正致力于在SQLAlchemy事件中找到一种方法,在属性更新并持久化到数据库中时调用外部API。以下是我的背景:
An
User
model with an attribute namedbirthday
. When an instance ofUser
model gets updated and saved, I want to call to an external API to update this user's birthday accordingly.
我尝试过Attribute Events,但是,它会产生太多的点击,而且无法保证set
/remove
属性事件最终会被持久化(auto commit设置为False,当发生错误时事务将回滚)
Session Events也不起作用,因为它需要一个Session/SessionFactory作为参数,而且基于代码的位置太多,以至于已经使用了Session。在
我一直在查看官方文档中所有可能的SQLAlchemy ORM event hooks,但是我找不到任何一个满足我的要求。在
我想知道是否还有人了解如何在SQLAlchemy中实现这种组合事件触发器。谢谢。在
可以通过组合多个事件来完成此操作。需要使用的特定事件取决于特定的应用程序,但基本思想是:
InstanceEvents.load
]当一个实例被加载时,请记下这个事实:它是被加载的,并且以后不会被添加到会话中(我们只想在加载实例时保存初始状态)AttributeEvents.set/append/remove
]当一个属性发生变化时,记下它被改变的事实,如果必要的话,它是从什么地方改变的(如果不需要初始状态,前两个步骤是可选的)SessionEvents.before_flush
]刷新发生时,记下实际保存的实例SessionEvents.before_commit
]在提交完成之前,记下实例的当前状态(因为在提交之后,您可能无法再访问它)SessionEvents.after_commit
]提交完成后,启动自定义事件处理程序并清除保存的实例一个有趣的挑战是事件的顺序。如果您执行
session.commit()
而不执行session.flush()
,您会注意到before_commit
事件在before_flush
事件之前触发,这与在session.commit()
之前执行session.flush()
的场景不同。解决方案是在您的before_commit
调用中调用session.flush()
来强制排序。这可能不是百分之百的洁净,但在生产中对我很有效。在以下是事件顺序的(简单)图表:
完整示例
^{pr2}$正如你所见,它有点复杂,也不太符合人体工程学。如果将它集成到ORM中会更好,但我也知道不这样做可能有原因。在
相关问题 更多 >
编程相关推荐