2013-03-26 86 views
5

問題是,我不知道如何使用SQLAlchemy來通知我什麼時候一個對象進入一個新的狀態。如何在數據庫更新後獲取SQLAlchemy ORM對象的先前狀態?

我使用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) 

我的代碼觸發每一次「設置」被稱爲該屬性,我檢查valueoldvalue是不同的。問題是target參數沒有完全形成,因此它沒有填充所有的屬性值。

有沒有更好的方法來做到這一點?謝謝!

回答

10

我的解決方案是使用'after_flush'SessionEvent而不是'set'AttributeEvent。

非常感謝agronholm誰提供了示例SessionEvent代碼,專門檢查對象的值和oldvalue。

下面的解決方案是他的代碼修改:

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的,值是事件處理程序。 sessionevent,inspectobject_mapper都是sqlalchemy類和函數。

相關問題