Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tracking model changes in SQLAlchemy

I want to log every action what will be done with some SQLAlchemy-Models.

So, I have a after_insert, after_delete and before_update hooks, where I will save previous and current representation of model,

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) 

But there is one problem: when I'm trying to find model in before_update hook, SQLA returns modified (dirty) version. How can I get previous version of model before updating it? Is there a different way to keep model changes?

Thanks!

like image 325
V. Gamula Avatar asked Apr 28 '15 13:04

V. Gamula


1 Answers

SQLAlchemy tracks the changes to each attribute. You don't need to (and shouldn't) query the instance again in the event. Additionally, the event is triggered for any instance that has been modified, even if that modification will not change any data. Loop over each column, checking if it has been modified, and store any new values.

@event.listens_for(cls, 'before_update') def before_update(mapper, connection, target):     state = db.inspect(target)     changes = {}      for attr in state.attrs:         hist = attr.load_history()          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 
like image 129
davidism Avatar answered Sep 20 '22 12:09

davidism