¿Cómo puedo obtener el estado anterior de un objeto ORM de SQLAlchemy después de una actualización de db?

El problema es que no puedo averiguar cómo usar SQLAlchemy para notificarme cuando un objeto entra en un nuevo estado.

Estoy usando SQLAlchemy ORM (Declarativo) para actualizar un objeto:

class Customer(declarative_base()): __table_name__ = "customer" id = Column(Integer, primary_key=True) status = Column(String) 

Quiero saber cuando un objeto entra en un estado. Particularmente después de que se haya emitido una ACTUALIZACIÓN y cuando el estado cambia. Por ejemplo, Customer.status == 'registered' y anteriormente tenía un estado diferente.

Actualmente estoy haciendo esto con un evento de atributo '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) 

Mi código se activa cada vez que se llama a ‘set’ en ese atributo, y compruebo si el value y el value oldvalue son diferentes. El problema es que el parámetro de target no está completamente formado, por lo que aún no se han completado todos los valores de los atributos.

¿Hay una mejor manera de hacer esto? ¡Gracias!

Mi solución fue usar ‘after_flush’ SessionEvent en lugar de ‘set’ AttributeEvent.

Muchas gracias a agronholm que proporcionó el código SessionEvent de ejemplo que verificó específicamente el valor y el valor antiguo de un objeto.

La solución a continuación es una modificación de su código:

 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) 

El registry es un diccionario cuyas claves son MapperProperty y cuyos valores son controladores de eventos. session , event , inspect y object_mapper son todas las clases y funciones de sqlalchemy.

use el evento before_update o el evento before_flush para interceptar que esto suceda en un momento posterior.