如何在db更新后获取SQLAlchemy ORM对象的先前状态?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在db更新后获取SQLAlchemy ORM对象的先前状态?相关的知识,希望对你有一定的参考价值。

问题是我无法弄清楚当对象进入新状态时如何使用SQLAlchemy通知我。

我正在使用SQLAlchemy ORM(声明性)来更新对象:

class Customer(declarative_base()):

    __table_name__ = "customer"

    id = Column(Integer, primary_key=True)
    status = Column(String)

我想知道一个物体进入状态的时间。特别是在发布UPDATE并且状态发生变化之后。例如。 Customer.status == 'registered'和以前有一个不同的州。

我目前正在使用'set'属性事件执行此操作:

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'时我的代码都会触发,我检查valueoldvalue是否不同。问题是target参数没有完全形成,因此它没有填充所有属性值。

有一个更好的方法吗?谢谢!

答案

我的解决方案是使用'after_flush'SessionEvent而不是'set'BeanntEvent。

非常感谢agronholm,他提供了专门检查对象值和oldvalue的示例SessionEvent代码。

下面的解决方案是对他的代码的修改:

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,其值是事件处理程序。 sessioneventinspectobject_mapper都是sqlalchemy类和功能。

另一答案

使用before_update事件或before_flush事件来拦截稍后发生的事件。

以上是关于如何在db更新后获取SQLAlchemy ORM对象的先前状态?的主要内容,如果未能解决你的问题,请参考以下文章

如果使用 ORM,是不是需要在 DB 中定义关系?

SqlAlchemy ORM

SQLAlchemy ORM

如何在 SQLAlchemy ORM 上实现对同一属性的自引用多对多关系?

SqlAlchemy ORM

如何将 SqlAlchemy 结果序列化为 JSON?