先说结论
在 Odoo 里,很多“按字段分组统计”“看板按阶段分列”“每列显示数量”的能力,背后通常不是前端自己算的,而是依赖:
read_groupgroup_bygroup_expand
如果把这几个概念理顺,你会更清楚为什么有些分组天然会出现,有些不会。
read_group 真正在做什么
最通俗地说,它就是:
按某个维度把记录聚起来,并顺手做统计。
所以它特别适合解决:
- 每个阶段有多少条
- 每个负责人名下多少单
- 每个月有多少金额
- 每个分类有多少记录
这和普通 search() 很不一样。
search() 更像找明细,read_group() 更像看汇总。
为什么看板分列总和它有关
因为看板按阶段分列,本质上就是一种分组结果展示。
例如 CRM 按阶段、任务按状态、工单按步骤,本质上都在问:
- 这批记录按某字段分组后,会形成哪些桶
- 每个桶里有多少条
所以看板“列”背后本质上就是一批 grouped result。
这也是为什么你调不好分组逻辑时,看板体验也会怪。
group_by 更像用户入口语义
group_by 可以理解成:
用户或入口声明:我想按这个维度看数据。
它不负责真正聚合实现本身,但它会把“按哪个维度分”这件事带进来。
所以你会在:
- 搜索视图
- action context
- 默认筛选
里经常看到它。
group_expand 为什么这么特别
这是很多人容易忽略但很值钱的点。
正常情况下,分组只会显示“当前有数据的组”。
但业务上有时你希望:
- 就算这个阶段暂时没有记录
- 这一列也得先显示出来
这时 group_expand 就特别重要。
它最像是在告诉系统:
分组结果不要只看当前有数据的桶,某些理论上应该出现的组选项也请展开出来。
这就是为什么很多看板可以提前显示空列。
为什么“没有数据的列还要显示”不是小需求
因为它影响的是业务流程可见性。
如果没有 group_expand,用户可能只看到“当前有数据的阶段”;
但业务管理常常需要看到“完整流程骨架”。
比如:
- 新建
- 处理中
- 待确认
- 已完成
就算某一列暂时为空,用户也希望知道这一步存在。
这时空列本身就是流程信息的一部分。
实战里最容易踩的 5 个坑
1. 把 search() 当统计方案硬用
明细和汇总不是一回事。
2. 只看到 group_by,却没理解底层还是 read_group
容易把问题看错层。
3. 以为没数据的组不显示是前端 bug
其实可能只是没做 group_expand。
4. 统计需求很复杂,却没先想清聚合维度
后面性能和结果都容易乱。
5. 把看板列当纯 UI 组件
忽略了它背后其实是一套聚合语义。
一句话记忆法
把这套机制记成一句话:
group_by负责声明按什么维度看,read_group负责真正做分组统计,group_expand负责把业务上应出现但暂时为空的组也展开出来。
理解这一句,看板和分组统计就不再神秘。
DISCUSSION
评论区