为什么这三个最容易混
因为它们看起来都像“业务逻辑”。
但其实它们解决的问题完全不同:
compute:算值onchange:前端表单交互联动constraints:校验数据是否合法
如果你把三者职责搞混,后面就很容易写出:
- 页面上看着对,保存后不对
- 前端能拦,后端却能绕过
- 数据能算出来,但时机又不对
1. compute:负责“算出来”
compute 的目标是:
根据别的字段,自动计算出一个字段值。
例如:
- 数量 × 单价 = 金额
- 开始时间 + 时长 = 结束时间
- 若干子记录汇总成总数
它关注的是:
- 字段之间的依赖关系
- 什么时候重新计算
- 结果存不存库(
store=True/False)
所以它是“算值机制”。
2. onchange:负责“表单联动”
onchange 的目标是:
用户在表单界面改了某个字段时,界面上立即联动调整别的值。
注意关键词:
- 表单界面
- 即时反馈
- 前端体验
比如:
- 选了客户后自动带出付款条件
- 改了产品后自动带出默认价格
- 改了数量后界面先预估一个金额
它不是数据底线,不是数据库规则,而是交互层优化。
3. constraints:负责“底线校验”
constraints 的目标是:
无论从哪里写入数据,只要不合法,就拒绝保存。
这才是“规则底线”。
比如:
- 折扣不能小于 0
- 结束时间必须晚于开始时间
- 数量不能为负数
- 同一编码不能重复
如果你只是用 onchange 做这些校验,那用户换个导入、RPC、自动化脚本,就可能绕过去。
所以:
- 体验问题 →
onchange - 数据底线 →
constraints
最容易记的一句话
- compute:我来算
- onchange:我来联动
- constraints:我来拦住
这句话非常好用。
常见误区
误区 1:把 onchange 当后端规则
这很危险。
因为 onchange 主要是给表单界面用的,不代表所有写入路径都会触发。
误区 2:用 constraints 代替 compute
校验和计算不是一回事。
- constraints 发现错了就报错
- compute 是主动给你算出值
误区 3:所有逻辑都塞进 compute
有些人会把业务判断、交互联动、校验全塞进 compute,结果字段之间依赖越来越乱。
一个简单的场景区分
假设你做一个报价单:
- 小计 = 数量 × 单价
- 改产品时,默认带出单价
- 数量必须大于 0
那就应该这样拆:
- 小计 →
compute - 改产品自动带单价 →
onchange - 数量必须 > 0 →
constraints
一旦这样分清楚,代码会清爽很多。
实战建议
1. 先问自己:这是“算值”还是“限制”还是“交互”
别一上来就写代码,先判类型。
2. 涉及数据底线,一定补 constraints
哪怕你前端已经做了联动和提示,也最好再加后端约束。
3. onchange 尽量轻量
它更适合做辅助体验,不要写太重的复杂业务流。
4. compute 要注意依赖
依赖写不全,字段可能不会按预期重算。
总结
Odoo 里这三个东西其实分工非常清楚:
- compute 负责算值
- onchange 负责表单联动
- constraints 负责数据底线校验
你以后只要先把这三个问题分清楚,再写逻辑,模型层代码会稳定很多。
DISCUSSION
评论区