いくつかの 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)
しかし、問題が 1 つあります。before_update フックでモデルを見つけようとすると、SQLA は変更された (ダーティな) バージョンを返します。更新する前に、モデルの以前のバージョンを取得するにはどうすればよいでしょうか。モデルの変更を保持する別の方法はありますか。
ありがとう!
ベストアンサー1
SQLAlchemy は各属性の変更を追跡します。イベントでインスタンスを再度クエリする必要はありません (また、クエリすべきではありません)。さらに、変更によってデータが変更されない場合でも、変更されたインスタンスに対してイベントがトリガーされます。各列をループして変更されたかどうかを確認し、新しい値を保存します。
@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