数据库更新后如何获取SQLAlchemy ORM对象的先前状态? [英] How can I get a SQLAlchemy ORM object's previous state after a db update?

查看:177
本文介绍了数据库更新后如何获取SQLAlchemy ORM对象的先前状态?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题是我无法弄清楚当对象进入新状态时如何使用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"时,我的代码都会触发,并且我检查valueoldvalue是否不同.问题在于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的键,其值是事件处理程序. sessioneventinspectobject_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对象的先前状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆