Odoo 开发

Odoo 上下文不是“随便塞参数”:default_、search_default_、group_by 的 UI 合约到底怎么生效

很多人知道 Odoo 里 context 很重要,但一到 action、菜单、搜索视图、默认值联动,就容易变成“哪里能塞就往哪里塞”。本文从官方源码与视图校验规则出发,讲清 default_、search_default_、group_by 这几类上下文键到底分别在跟谁说话。

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

Odoo 开发里,context 是那种“人人都知道重要,但也人人都容易越用越乱”的东西。

尤其是这些写法:

  • default_partner_id
  • search_default_my_records
  • group_by
  • default_type
  • active_id

很多时候项目里会逐渐变成一种模糊经验:

反正 context 很神,想让界面默认成什么样,就先往里塞一把试试。

但从 /home/ubuntu/odoo-temp/odoo/addons/base/models/ir_ui_view.py 和整个 Web/ORM 交互的语义来看,context 不是“万能口袋”,而是一套前后端之间约定好的 UI 合约。不同 key,其实是在对不同层说话。

一、先把问题分清:不是所有 context key 都在做同一件事

开发里最常混的三类 key 是:

1)default_...

这是在对“新建记录的默认值”说话。

例如:

{'default_partner_id': partner.id}

它的语义是:当用户打开创建表单时,如果新记录里有 partner_id 这个字段,就把默认值设成这里给的内容。

2)search_default_...

这是在对“搜索视图里的默认筛选器”说话。

例如:

{'search_default_my_orders': 1}

它不是给模型字段赋值,也不是 domain 本身,而是在告诉搜索面板:

  • 如果存在名为 my_orders 的 filter
  • 默认帮我勾上它

3)group_by

这是在对“当前列表/报表/聚合界面默认按什么分组”说话。

它和 default_ 的语义完全不是一类。

如果把这三类混成“都是 context 里某个参数”,后面很容易越改越乱。

二、default_ 的核心边界:它影响新建默认值,不等于落库值

很多人会误以为:

context = {'default_xxx': value}

等于“这个字段一定会是这个值”。

其实不是。

更准确地说,它影响的是:

  • 新建表单初始化时
  • default_get() / 默认值链路
  • 记录刚开始长出来时的初始状态

后面用户仍然可以:

  • 手工改掉
  • 被 onchange 改掉
  • 被 create/write 逻辑重算

所以 default_ 的边界是“初始建议值”,不是“最终落库强制值”。

这也是为什么 context 默认值经常和 default_get()、onchange 一起看,单看一层很容易误判。

三、search_default_ 的核心边界:它激活的是搜索项,不是直接拼 domain

这是另一类特别容易被误解的键。

很多人看到:

{'search_default_customer': 1}

会下意识理解成“给 domain 加 customer 过滤”。

但它真正的语义更像:

  • 搜索视图里如果有一个对应 filter
  • 默认勾选它
  • 再由这个 filter 自己定义 domain / context / group 展现

所以如果你塞了一个 search_default_xxx 却没效果,先别急着怀疑 action context 丢了,更该先检查:

  • 搜索视图里到底有没有对应名字的 filter
  • 这个 filter 定义的到底是什么
  • 当前 action / view 是否真的用了那张 search view

也就是说,search_default_对搜索 UI 组件发信号,不是 ORM domain 的直接替身。

四、group_by 真的是被显式校验的,不是你想写什么都行

这一点在 ir_ui_view.py 里非常清楚。

Odoo 在校验 XML 视图节点的 context 属性时,会专门检查其中的 group_by

  • 它必须是字符串
  • 字符串里引用的字段必须真实存在于模型上

源码甚至直接在视图校验阶段抛出类似:

  • "group_by" value must be a string
  • Unknown field ... in "group_by" value

这说明 group_by 不是“前端自己猜着用”的自由文本,而是一个被框架明确验证的上下文协议。

这也解释了为什么有些 XML 明明能安装别的 context key,却会在 group_by 上直接报视图错误:因为它是有结构约束的。

五、为什么说这些 key 是“在跟不同对象说话”

这是理解 context 最有帮助的角度。

default_...

在跟:

  • 默认值计算链
  • 新建表单初始化
  • default_get()

说话。

search_default_...

在跟:

  • 搜索视图
  • 筛选器开关
  • 搜索 UI 状态

说话。

group_by

在跟:

  • 当前视图的默认分组
  • 分组字段校验规则
  • Web 客户端的 group 展现逻辑

说话。

把它们统称为“都是 context 参数”当然没错,但这会掩盖它们其实面向不同消费方。

六、最常见的项目级误用

误用 1:想强制字段值,却只塞 default_

如果你的需求是“这个字段最终不能被改”,那你靠 default_ 往往不够。它只是初始值入口。

误用 2:以为 search_default_ 不生效是模型问题

很多时候根因根本不在模型,而在:

  • filter 名字不匹配
  • search view 没挂上
  • 当前 action 用的不是你以为那张搜索视图

误用 3:把 group_by 当成任意表达式

源码已经明确告诉你,它不是随便写的;字段名不对、格式不对,视图层就会拦下来。

七、一个更稳定的排查顺序

以后碰到“为什么 context 没按我想的生效”,建议先问:

第一步:这个 key 想影响的是哪一层?

  • 默认值
  • 搜索 UI
  • 分组表现
  • 还是别的 ORM 行为

第二步:这一层是否真的消费这个 key?

比如:

  • search_default_foo 有没有对应 filter
  • group_by 的字段是不是存在
  • default_bar 对应字段在创建链上会不会马上被 onchange 改掉

第三步:是否把“初始状态”误认为“最终结果”

很多 context bug,本质上不是 key 失效,而是后续链路又把初始值改掉了。

结语

Odoo 里的 context 强大,但它不是“往里塞参数,系统自然会懂”的黑盒。

更准确的理解应该是:

  • default_... 负责新建默认值
  • search_default_... 负责默认激活搜索筛选器
  • group_by 负责默认分组,而且会被视图层严格校验

所以真正该掌握的不是“context 很神”,而是:

每一种 context key,都有它明确的消费方和边界;一旦把消费方搞错,行为就会看起来像失灵。

DISCUSSION

评论区

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