先说结论
很多 Odoo 计算字段“改了却没更新”的问题,表面像缓存怪异,实际常见根因是:
系统并不知道哪些字段变化应该触发这条 compute 结果重算。
而这件事最核心的入口,往往就是 @api.depends()。
所以 depends 不是装饰语法,而是在告诉 ORM:
- 这条结果依赖谁
- 谁变了就该重新算
为什么这类问题总让人觉得像玄学
因为用户看到的是:
- A 字段都改了
- 为什么 B 这个计算结果没跟上?
如果不理解重算链,你就很容易觉得:
- 系统缓存坏了
- ORM 不稳定
- 需要多刷新几次
但更常见的现实是:
- 你脑子里知道 B 依赖 A
- 可 ORM 并没有被明确告知这层依赖
所以它不会自动替你猜。
depends 真正在声明什么
它最本质是在说:
当这些字段变化时,这个计算结果应该被视为过期并重新计算。
这点特别关键。
因为 compute 本身只说明“怎么算”, 而 depends 说明的是“什么时候必须重算”。
一个是计算公式,一个是失效条件。
为什么“计算逻辑写对了”还不够
因为系统不仅要知道公式,还要知道触发时机。
如果 depends 没写全,常见结果就是:
- 某些场景下能更新
- 某些场景下又像没反应
这时你会误以为 ORM 很随机。
其实很多时候不是随机,而是:
- 某条变化路径根本没进入重算触发链。
为什么跨字段、跨关系依赖更容易漏
因为你脑中想的是业务语义:
- 这个结果当然也受那个对象影响
但系统需要的是:
- 具体哪条字段路径会触发失效
这就是为什么一旦关系链变深,depends 更容易漏写。
不是因为逻辑变神秘,而是因为触发路径变长了。
为什么很多“缓存问题”其实不是缓存问题
有些现象看起来像缓存没刷新:
- 重新进页面又好了
- 某些入口改了会更新,另一些不会
这很容易让人怪缓存。
但如果 depends 声明不完整,就会出现这种“像缓存,其实是失效条件没声明全”的假象。
所以排查时,最好先问:
- 这条 compute 的依赖路径有没有完整告诉 ORM?
实战里最容易踩的 5 个坑
1. 只写 compute,不认真写 depends
重算触发会不稳。
2. 以为系统会自动理解所有业务依赖
ORM 不会替你猜全。
3. 关系链依赖漏写
这是高频问题。
4. 把失效条件问题误判成缓存问题
排查方向会跑偏。
5. 看到某些场景能更新,就以为整体没问题
其实可能只是命中了部分路径。
一句话记忆法
把它记成一句话:
compute 说明“怎么算”,depends 说明“谁变了必须重算”;很多看起来像缓存异常的问题,本质上其实是重算依赖没声明完整。
理解这一句,计算字段问题会清楚很多。
DISCUSSION
评论区