症状
ORM 对象在会话内能正常加载,但之后读取属性或遍历关系时抛出 DetachedInstanceError: Instance is not bound to a Session。该故障常出现在响应序列化、模板渲染或会话关闭或过期后才拿到对象的后台任务中。
诊断
定位属性访问相对会话的位置;检查 expire_on_commit 是否在提交后使属性过期;对需要的关系使用 joinedload 等预加载。
grep -n "with Session\|session.close\|expire_on_commit" app/
根因
ORM 对象只有在与会话绑定时才惰性加载属性。会话关闭后,延迟的属性或关系访问没有会话可查询,于是 SQLAlchemy 抛出 DetachedInstanceError。
修复
在访问属性期间保持会话开启,预加载所需关系,或在离开会话作用域前把对象转换为纯数据。仅关闭过期机制并非修复,因为分离后的惰性加载仍会失败。
验证
修改后在会话外读取此前失败的属性,确认返回数据而非抛错;把加载值与数据库对照可验证预加载取到了正确的行。
常见陷阱
用 try/except 吞掉异常并返回空值会隐藏数据缺失;应让属性在会话内可用。