我想记录一些SQLAlchemy-Models将要完成的操作。
所以,我有一个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返回修改(脏)版本。 如何在更新之前获取以前版本的模型? 是否有不同的方法来保持模型更改?
谢谢!
答案 0 :(得分:19)
SQLAlchemy跟踪每个属性的更改。您不需要(并且不应该)在事件中再次查询实例。此外,即使该修改不会更改任何数据,也会针对已修改的任何实例触发事件。循环遍历每一列,检查它是否已被修改,并存储任何新值。
// Doubly linked list
#include <stdio.h>
struct entry
{
int value;
struct entry *next;
struct entry *prev;
};
void dubbleNext (struct entry *e) {
if (e != '\0') {
printf ("%d\n", e->value);
dubbleNext(e->next);
}
}
void dubblePrev (struct entry *e) {
if (e != '\0') {
printf ("%d\n", e->value);
dubbleNext(e->prev);
}
}
int main (void)
{
struct entry n1, n2, n3;
int i;
n1.value = 100;
n2.value = 200;
n3.value = 300;
n1.next = &n2;
n2.next = &n3;
n3.next = NULL;
n1.prev = NULL;
n2.prev = &n1;
n3.prev = &n2;
dubbleNext (&n1);
dubblePrev (&n3);
return 0;
}
答案 1 :(得分:1)
我无法发表评论,但要解决大卫所回答的问题:
如果某个属性已过期(默认情况下会在提交时执行哪些会话),则除非在更改之前加载旧值,否则旧值不可用。您可以通过检查看到这一点。
state = inspect(entity)
session.commit()
state.attrs.my_attribute.history # History(added=None, unchanged=None, deleted=None)
# Load history manually
state.attrs.my_attribute.load_history()
state.attrs.my_attribute.history # History(added=(), unchanged=['my_value'], deleted=())
为了使属性保持加载状态,您无法通过会话expire_on_commit
将实体到期为False。
答案 2 :(得分:0)
我有一个类似的问题,但是我希望能够跟踪增量,因为对sqlalchemy模型进行了更改,而不仅仅是更改了新值。我为davidism's答案写了这个扩展名,以达到更好的处理bar
和before
的目的,因为有时它们是列表或空元组:
after