Flask-SQLAlchemy事件监听器无法获取更新前的旧数据库数据
解决Flask-SQLAlchemy审计日志中获取更新前旧数据的问题
你遇到的问题根源在于:before_update事件触发时,目标对象已经被修改,且SQLAlchemy会话会缓存当前对象的最新状态,直接通过User.query.get(target.id)查询会返回会话中已修改的对象,而非数据库里的原始数据。
正确的做法是使用SQLAlchemy的inspect工具获取对象的提交前原始状态,无需额外查询数据库。修改后的代码如下:
from flask_sqlalchemy import SQLAlchemy from sqlalchemy import event, inspect from flask import Flask app = Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///db" db = SQLAlchemy(app) class User(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100)) email = db.Column(db.String(100)) with app.app_context(): db.drop_all() db.create_all() @event.listens_for(User, 'before_update') def receive_before_update(mapper, connection, target): # 获取对象的提交前原始状态 state = inspect(target) committed_state = state.committed_state # 提取原始值,若字段未修改则使用当前值作为 fallback original_name = committed_state.get('name', target.name) original_email = committed_state.get('email', target.email) # 记录变更 print(f"Updating user: {original_name} ({original_email}) to {target.name} ({target.email})") # 添加新用户 new_user = User(name="First_User", email="s@s.com") with app.app_context(): db.session.add(new_user) db.session.commit() # 更新用户名称 with app.app_context(): update_record = User.query.filter_by(name="First_User").first() update_record.name = "new_name" db.session.commit()
关键说明:
inspect(target)获取对象的状态实例,committed_state属性存储了对象在数据库中的原始值(未被本次修改覆盖的状态)。- 调用
committed_state.get()时,若字段未被修改,会返回None,因此用target.name作为 fallback 保证逻辑完整。
运行修改后的代码,输出会符合预期:
Updating user: First_User (s@s.com) to new_name (s@s.com)
内容的提问来源于stack exchange,提问作者ZDRuX
相关产品推荐
相关产品推荐

