视图后处理

Odoo 视图为什么像“会自己变”:get_view、postprocess_and_fields、modifiers 和缓存到底怎么接力

很多人会写 XML 视图,却不清楚同一个 view 为什么到了不同用户、语言或移动端会长得不一样。本文从官方源码讲清 Odoo 在 get_view 之后如何做后处理、权限裁剪、modifiers 生成与缓存。

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

先说结论

很多开发者以为 XML 视图文件就是“前端最终长相”。

其实在 Odoo 里,XML 只是起点。

官方源码在 ir_ui_view.py 里展示得很清楚:一个视图真正发给前端之前,还要经历:

  • 继承合并后的 arch 获取
  • postprocess
  • 访问权限和 groups 裁剪
  • modifiers 处理
  • 子视图补齐
  • 缓存命中 / 回填

所以更准确地说:

用户看到的 view,不是你写下的 XML 原件,而是 Odoo 按当前上下文“加工后”的结果。


为什么同一个 view 会“对不同人长不一样”

因为视图不是静态文件渲染,而是上下文相关的结构生成

源码里的 _get_view_cache_key() 已经把这个思路写出来了。

默认 cache key 至少会考虑:

  • view_id
  • view_type
  • mobile
  • 当前语言 lang
  • 以及 context 里结尾为 _view_ref 的值

这意味着哪怕你写的是同一份 XML:

  • 语言变了
  • 移动端 / 桌面端不同
  • 某些引用视图不同

最终拿到的 view 结果都可能不是同一份。


主链路怎么走

第一步:先拿到组合后的 view 架构

_get_view_cache() 会先调用 _get_view(),拿到基础 arch 和 view 信息。

这时的重点还是“视图结构本身”。

但这还不是最终给前端的版本。

第二步:进入 _get_view_postprocessed()

源码注释写得很直白:

  • 应用 access control rules
  • 应用 field modifiers
  • 处理 tag-specific logic
  • 必要时补 one2many / many2many 的 subviews
  • 收集涉及到的字段

也就是说,从这里开始,视图不再只是 XML,而开始变成:

一个带权限、交互属性和字段描述的可执行 UI 结构。

第三步:postprocess_and_fields() 真正做后处理

postprocess_and_fields() 会先 _postprocess_view(...),然后把 arch 和模型字段集合整理出来。

这一步背后的重点是:

  • 不是只返回 arch 字符串
  • 还要返回这个 view 用到了哪些模型字段

因为前端不只是要“画出来”,还要知道字段是什么、怎么显示、受什么约束。


groups、权限和 modifiers 是怎么进来的

这是最容易被误以为“前端魔法”的部分。

groups 不是前端自己猜的

源码里的 _postprocess_access_rights() 会:

  • 根据当前用户 group
  • 把不该看到的节点直接移掉
  • 对某些节点写入 create / edit / delete / can_create / can_write 等限制

所以很多“为什么这个按钮有的人看得到、有的人没了”的现象,并不是前端临时隐藏,而是后端在返回 view 之前就做了裁剪。

modifiers 也不是单纯 XML 原样透传

源码还有 _modifiers_from_model()、postprocess 相关逻辑,把:

  • readonly
  • required
  • invisible
  • 以及模型层字段特征

整理成前端可消费的 modifiers 语义。

所以你写在 XML 里的条件,并不是终点,而是 modifiers 生成过程的输入之一。


为什么缓存很关键

如果每次打开页面都完整跑一遍:

  • 视图继承合并
  • 后处理
  • 权限裁剪
  • 子视图展开
  • 字段收集

开销会相当可观。

所以 _get_view_cache() 会把“后处理后的视图结果”缓存起来。

但这里有一个很重要的边界:

能进入缓存 key 的上下文,才有资格安全影响返回结果。

源码的 docstring 甚至明确提醒:

  • 返回值只能依赖某些允许的维度
  • 不能随便把任意 context 都掺进 view 结果

否则你会得到很难排查的缓存错乱。

这也是为什么自定义 _get_view() / _get_view_cache_key() 时必须非常克制。


新手最容易误解的 4 个点

1. 以为 XML 就是最终界面

实际上 XML 只是输入材料。

2. 以为按钮显示隐藏都是 JS 控的

很多权限和 groups 裁剪在后端 postprocess 阶段就已经发生。

3. 以为 modifiers 只是前端小配置

它们其实是模型、视图、权限共同作用后的 UI 约束表达。

4. 以为自定义 _get_view() 时可以随便用 context 改结果

如果结果没有正确进入 cache key,后面非常容易出现“这个用户看到的是上一个人的视图”之类的错乱感。


实战开发该怎么用这层理解

如果你在做复杂视图定制,我建议按这个顺序排查:

  1. 先确认继承后的 arch 到底是什么
  2. 再看 groups / access rights 是否把节点裁掉了
  3. 再看 modifiers 是否被模型或字段属性补强
  4. 最后再怀疑前端显示层

很多“我明明 XML 写对了为什么还是不显示”的问题,根本不在 XML 本身,而在 view postprocess 之后。


一句话记忆法

Odoo 的 view 不是静态 XML,而是 _get_view 取结构、postprocess_and_fields 加规则、modifiers 补交互、缓存做复用之后,才交给前端的上下文化结果。

理解这条链,写视图和查视图问题都会稳很多。

DISCUSSION

评论区

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