问题描述
问题是我无法弄清楚当对象进入新状态时如何使用SQLAlchemy通知我.
The issue is that I can't figure out how to use SQLAlchemy to notify me when an object goes into a new state.
我正在使用SQLAlchemy ORM(声明性)来更新对象:
I'm using SQLAlchemy ORM (Declarative) to update an object:
class Customer(declarative_base()):
__table_name__ = "customer"
id = Column(Integer, primary_key=True)
status = Column(String)
我想知道对象何时进入状态.特别是在发出UPDATE之后以及状态改变时.例如. Customer.status == 'registered'
,它以前具有不同的状态.
I want to know when an object enters a state. Particularly after an UPDATE has been issued and when the state changes. E.g. Customer.status == 'registered'
and it previously had a different state.
我目前正在通过'set'
属性事件来执行此操作:
I'm currently doing this with an 'set'
attribute event:
from sqlalchemy import event
from model import Customer
def on_set_attribute(target, value, oldvalue, initiator):
print target.status
print value
print oldvalue
event.listen(
Customer.status,
'set',
on_set_attribute,
propagate=True,
active_history=True)
每次在该属性上调用"set"时,我的代码都会触发,并且我检查value
和oldvalue
是否不同.问题在于target
参数的格式不完整,因此尚未填充所有属性值.
My code fires every time 'set' is called on that attribute, and I check if the value
and the oldvalue
are different. The problem is that the target
parameter isn't fully formed so it doesn't have all the attribute values populated yet.
是否有更好的方法可以做到这一点?谢谢!
Is there a better way to do this? Thanks!
推荐答案
我的解决方案是使用"after_flush" SessionEvent而不是"set" AttributeEvent.
My solution was to use 'after_flush' SessionEvent instead of 'set' AttributeEvent.
非常感谢 agronholm 提供了示例SessionEvent代码,该代码专门检查了对象的值和oldvalue.
Many thanks to agronholm who provided example SessionEvent code that specifically checked an object's value and oldvalue.
下面的解决方案是对他的代码的修改:
The solution below is a modification of his code:
def get_old_value(attribute_state):
history = attribute_state.history
return history.deleted[0] if history.deleted else None
def trigger_attribute_change_events(object_):
for mapper_property in object_mapper(object_).iterate_properties:
if isinstance(mapper_property, ColumnProperty):
key = mapper_property.key
attribute_state = inspect(object_).attrs.get(key)
history = attribute_state.history
if history.has_changes():
value = attribute_state.value
# old_value is None for new objects and old value for dirty objects
old_value = get_old_value(attribute_state)
handler = registry.get(mapper_property)
if handler:
handler(object_, value, old_value)
def on_after_flush(session, flush_context):
changed_objects = session.new.union(session.dirty)
for o in changed_objects:
trigger_attribute_change_events(o)
event.listen(session, "after_flush", on_after_flush)
registry
是一本字典,其键是MapperProperty的键,其值是事件处理程序.session
,event
,inspect
和object_mapper
都是sqlalchemy类和函数.
The registry
is a dictionary whose keys are MapperProperty's and whose values are event handlers.session
, event
, inspect
, and object_mapper
are all sqlalchemy classes and functions.
这篇关于数据库更新后如何获取SQLAlchemy ORM对象的先前状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!