很多人第一次改 Odoo 页面,都会本能地想:
我把原 XML 复制一份,改完再替换掉不就行了吗?
这通常是最容易把项目改崩的做法。
Odoo 的视图系统更像“在原图上打补丁”,而不是“整页重画”。inherit_id、xpath 和 position 就是这套机制的三把钥匙。
先理解 inherit_id:你继承的是“节点”,不是整份文件
在 website_sale/views/product_views.xml 里,你会看到很多这种结构:
<record id="product_template_view_tree_website_sale" model="ir.ui.view">
<field name="inherit_id" ref="website_sale.product_template_view_tree"/>
</record>
意思不是“把父视图抄一遍”,而是:
- 我先认这个父视图;
- 再只描述我要改哪一小块;
- 最后由 Odoo 合成最终视图。
所以继承视图的核心思路是 增量修改。
xpath 负责精准定位,position 负责说明怎么改
最常见的写法像这样:
<field name="default_code" position="after">
<field name="website_id" groups="website.group_multi_website" optional="hide"/>
</field>
这句话的意思很直白:
- 先找到
default_code这个节点; - 然后在它后面插入新字段。
再看 website_event_crm/views/event_lead_rule_views.xml:
<xpath expr="//field[@name='lead_creation_basis']" position="attributes">
<attribute name="column_invisible">False</attribute>
</xpath>
这就不是插入,而是直接修改目标节点的属性。
所以 position 不是装饰,它决定的是:
beforeafterinsidereplaceattributes
不同位置对应完全不同的改法。
一个很重要的区分:插字段和改属性不是一回事
很多新手会把这两种操作混着写,最后发现视图没有按预期变化。
插入内容
适合:
- 增加字段;
- 增加按钮;
- 增加提示文案;
- 增加一段 QWeb 结构。
改属性
适合:
- 让原字段可见或不可见;
- 改
readonly; - 改
required; - 改列显示方式;
- 改 class、style、widget 等属性。
这就是为什么同样是“改页面”,有时你写的是 field position="after",有时则必须用 xpath position="attributes"。
website_sale 里的例子很好懂
product_template_view_tree_website_sale 会在产品列表里插入:
website_sequencepublic_categ_idsis_published
这些都不是重画整张列表,而是在原来产品列表的基础上补出网站销售需要的字段。
这背后的理念很清楚:
业务差异越小,视图补丁就越小。
templates.xml 里的 QWeb 继承也是同一套路
在 website_sale/views/templates.xml 里,像 header_hide_empty_cart_link 这种继承模板,会先继承 website_sale.header_cart_link,再通过 xpath 把 show_cart 的逻辑改掉。
这说明 QWeb 和传统 form/tree 视图虽然长得不一样,但继承思路是一致的:
- 先定位;
- 再插针;
- 再让合成器生成最终页面。
新手最容易犯的三个错
1)XPath 太宽
比如匹配了多个节点,结果插进去了不该插的位置。
2)改错层
有些改动该在 form 视图做,你却在 QWeb 做;或者该在模板层改,你却在 backend tree 里硬找。
3)把 mode="primary" 当成“我想强行覆盖父视图”
primary 只是说明这个视图在某些场景下作为主要视图参与解析,不代表你可以不顾继承链随便写。
调试视图时,建议你这样想
- 先确认父视图是谁;
- 再确认你要改的是节点内容还是节点属性;
- 再确认 XPath 是否只命中一个目标;
- 最后看 position 是否真的符合你的意图。
只要这四步顺了,视图继承通常就不神秘了。
一句话总结
Odoo 视图继承不是复制粘贴,而是:
用
inherit_id绑定父视图,用xpath找到目标节点,再用position精准修改原页面。
DISCUSSION
评论区