2015-04-28 16 views
9

Desidero registrare ogni azione che verrà eseguita con alcuni modelli SQLAlchemy.Rilevamento delle modifiche del modello in SQLAlchemy

Così, ho un after_insert, after_delete e before_update ganci, dove mi salverò rappresentazione precedente e attuale del modello,

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) 

Ma c'è un problema: quando sto cercando di trovare il modello in before_update hook, SQLA restituisce la versione modificata (sporca). Come posso ottenere una versione precedente del modello prima di aggiornarlo? Esiste un modo diverso per mantenere le modifiche del modello?

Grazie!

risposta

9

SQLAlchemy tiene traccia delle modifiche apportate a ciascun attributo. Non è necessario (e non dovrebbe) interrogare nuovamente l'istanza nell'evento. Inoltre, l'evento viene attivato per qualsiasi istanza che è stata modificata, anche se tale modifica non modificherà alcun dato. Passa su ogni colonna, controllando se è stata modificata e memorizza eventuali nuovi valori.

@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