2015-04-28 77 views
9

我想記錄每個操作將使用某些SQLAlchemy模型執行的操作。在SQLAlchemy中跟蹤模型更改

所以,我有一個after_insert,after_delete和before_update鉤,在這裏我將節省模型的以前和當前的表示,

def keep_logs(cls): 
    @event.listens_for(cls, 'after_delete') 
    def after_delete_trigger(mapper, connection, target): 
     pass 

    @event.listens_for(cls, 'after_insert') 
    def after_insert_trigger(mapper, connection, target): 
     pass 

    @event.listens_for(cls, 'before_update') 
    def before_update_trigger(mapper, connection, target): 
     prev = cls.query.filter_by(id=target.id).one() 
     # comparing previous and current model 


MODELS_TO_LOGGING = (
    User, 
) 
for cls in MODELS_TO_LOGGING: 
    keep_logs(cls) 

但有一個問題:當我試圖找到before_update模型鉤子,SQLA返回修改(髒)版本。 如何在更新之前獲取舊版本的模型? 有沒有不同的方式來保持模型的變化?

謝謝!

回答

9

SQLAlchemy跟蹤每個屬性的更改。您不需要(也不應該)在事件中再次查詢實例。此外,即使該修改不會更改任何數據,也會觸發該事件被修改的任何實例。循環遍歷每列,檢查它是否已被修改,並存儲任何新值。

@event.listens_for(cls, 'before_update') 
def before_udpate(mapper, connection, target): 
    state = db.inspect(target) 
    changes = {} 

    for attr in state.attrs: 
     hist = state.get_history(attr.key, True) 

     if not hist.has_changes(): 
      continue 

     # hist.deleted holds old value 
     # hist.added holds new value 
     changes[attr.key] = hist.added 

    # now changes map keys to new values