Selection 扩展

Odoo 扩展 Selection 字段别只会加选项:selection_add 和 ondelete 的真正边界

很多人会给 Selection 字段直接加新状态,却忽略了 selection_add 和 ondelete 背后的兼容边界。本文把它讲透。

Odoo 开发
进阶 开发者 1 分钟阅读
0 评论 0 点赞 0 收藏 9 阅读

先说结论

在 Odoo 里,扩展已有 Selection 字段时,真正安全的思路通常不是整段重写,而是:

  • selection_add 扩展已有选项
  • ondelete 说明这个新增选项未来失效时怎么办

也就是说,selection_add 解决的是怎么加新值ondelete 解决的是以后不想要这个值时怎么收场


为什么直接重写 selection 很危险

因为你扩展的往往不是你自己独占的字段。

很多 Selection 字段来自:

  • 基础模块
  • 别的官方模块
  • 第三方模块
  • 未来还可能继续被别的模块扩展

如果你直接整段覆盖,风险是:

  • 把别人的选项覆盖掉
  • 升级后官方新增选项丢失
  • 多模块同时继承时顺序变脆

所以官方源码也明确提示:如果只是扩展已有选项,优先使用 selection_add


selection_add 真正在表达什么

它表达的是:

不要推翻原来的选择集合,只是在现有集合上追加或插入新的业务值。

这和 _inherit 的整体设计哲学是一致的:优先扩展,不轻易重写,尽量保持兼容。


为什么 ondelete 不是可有可无的小参数

它解决的是一个非常现实的问题:

如果你这个模块以后卸载了,或者你新增的 selection 选项以后被移除了,那历史数据怎么办?

假设你给某状态字段加了一个新值:custom_review

如果某天这个值不再存在,系统就必须知道:

  • 设为空?
  • 改回默认值?
  • 改成另一个安全值?
  • 直接删记录?
  • 用自定义逻辑迁移?

ondelete 说的就是这个“退场策略”。


官方源码给你的核心启发

fields_selection.py 里,官方把 ondelete 描述得很明确:

  • set null
  • cascade
  • set default
  • set VALUE
  • 或者 callable

这说明 Odoo 并不是把 Selection 当成纯前端下拉框,而是当成一种会沉淀到历史数据里的业务状态值


新手最容易踩的 4 个坑

1. 只加新值,不想退场策略

开发阶段觉得没问题,后面模块卸载、状态废弃、升级清理时就开始痛。

2. 用整段 selection 覆盖而不是 selection_add

短期能跑,长期兼容性很差。

3. 把 Selection 当成随便加几个字符串

其实每个值背后都可能对应:

  • 视图状态
  • 按钮条件
  • 权限边界
  • 业务流程分支
  • 历史数据语义

4. ondelete 选错策略

比如本来应该 set default,你却用 cascade,那代价可能非常大。


一句话记忆法

selection_add 决定怎么把新状态接进来,ondelete 决定这个状态以后退场时怎么不把数据搞坏。

DISCUSSION

评论区

想参与讨论?先 登录 再发表评论。
还没有评论,你可以成为第一个留言的人。