先说结论
很多开发者以为 XML 视图文件就是“前端最终长相”。
其实在 Odoo 里,XML 只是起点。
官方源码在 ir_ui_view.py 里展示得很清楚:一个视图真正发给前端之前,还要经历:
- 继承合并后的 arch 获取
- postprocess
- 访问权限和 groups 裁剪
- modifiers 处理
- 子视图补齐
- 缓存命中 / 回填
所以更准确地说:
用户看到的 view,不是你写下的 XML 原件,而是 Odoo 按当前上下文“加工后”的结果。
为什么同一个 view 会“对不同人长不一样”
因为视图不是静态文件渲染,而是上下文相关的结构生成。
源码里的 _get_view_cache_key() 已经把这个思路写出来了。
默认 cache key 至少会考虑:
view_idview_typemobile- 当前语言
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 相关逻辑,把:
readonlyrequiredinvisible- 以及模型层字段特征
整理成前端可消费的 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,后面非常容易出现“这个用户看到的是上一个人的视图”之类的错乱感。
实战开发该怎么用这层理解
如果你在做复杂视图定制,我建议按这个顺序排查:
- 先确认继承后的 arch 到底是什么
- 再看 groups / access rights 是否把节点裁掉了
- 再看 modifiers 是否被模型或字段属性补强
- 最后再怀疑前端显示层
很多“我明明 XML 写对了为什么还是不显示”的问题,根本不在 XML 本身,而在 view postprocess 之后。
一句话记忆法
Odoo 的 view 不是静态 XML,而是
_get_view取结构、postprocess_and_fields加规则、modifiers 补交互、缓存做复用之后,才交给前端的上下文化结果。
理解这条链,写视图和查视图问题都会稳很多。
DISCUSSION
评论区