What Is View Inheritance?
View inheritance lets you modify existing views without replacing them entirely. Using XPath expressions, you can insert new fields, change attributes, hide elements, and add buttons to any standard or third-party view.
Basic Structure
<record id="view_partner_form_inherit" model="ir.ui.view">
<field name="name">res.partner.form.inherit.my_module</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<!-- XPath modifications go here -->
</field>
</record>XPath Operations
Insert After
<!-- Add a field after an existing field -->
<xpath expr="//field[@name='phone']" position="after">
<field name="loyalty_points"/>
</xpath>Insert Before
<!-- Add a field before an existing field -->
<xpath expr="//field[@name='email']" position="before">
<field name="preferred_contact_method"/>
</xpath>Insert Inside (Append)
<!-- Add content inside an element (at the end) -->
<xpath expr="//group[@name='sale']" position="inside">
<field name="credit_limit"/>
<field name="payment_terms"/>
</xpath>Replace
<!-- Replace an element entirely -->
<xpath expr="//field[@name='website']" position="replace">
<field name="website" widget="url" placeholder="https://..."/>
</xpath>
<!-- Remove an element (replace with nothing) -->
<xpath expr="//field[@name='fax']" position="replace"/>Modify Attributes
<!-- Change field attributes -->
<xpath expr="//field[@name='name']" position="attributes">
<attribute name="required">True</attribute>
<attribute name="placeholder">Enter full name</attribute>
</xpath>
<!-- Make a field invisible -->
<xpath expr="//field[@name='fax']" position="attributes">
<attribute name="invisible">True</attribute>
</xpath>
<!-- Add CSS class -->
<xpath expr="//div[@class='oe_title']" position="attributes">
<attribute name="class">oe_title text-primary</attribute>
</xpath>XPath Expression Cheat Sheet
| Expression | Matches |
|---|---|
//field[@name='phone'] | Field with name="phone" anywhere |
//group[@name='sale'] | Group with name="sale" |
//page[@name='notes'] | Notebook page named "notes" |
//notebook | First notebook element |
//sheet | The form sheet |
//header | The form header (status bar area) |
//button[@name='action_confirm'] | Button with name="action_confirm" |
//div[@class='oe_title'] | Div with class="oe_title" |
//label[@for='field_name'] | Label for a specific field |
//separator[@string='Notes'] | Separator with string="Notes" |
//field[@name='line_ids']/list | List view inside a One2many |
//field[@name='line_ids']/list//field[@name='price'] | Field inside embedded list |
Shorthand Syntax (Without XPath)
<!-- Odoo supports shorthand for common cases: -->
<!-- Instead of xpath, use the element directly: -->
<field name="phone" position="after">
<field name="loyalty_points"/>
</field>
<!-- This works for field, group, page, notebook, button, div -->
<!-- But XPath is more flexible and reliable for complex selectors -->Real-World Examples
Add a Tab to the Partner Form
<xpath expr="//notebook" position="inside">
<page string="Equipment" name="equipment">
<field name="equipment_ids">
<list>
<field name="name"/>
<field name="serial_number"/>
<field name="status"/>
</list>
</field>
</page>
</xpath>Add a Button to the Header
<xpath expr="//header" position="inside">
<button name="action_send_reminder"
string="Send Reminder"
type="object"
class="btn-primary"
invisible="state != 'overdue'"/>
</xpath>Add a Smart Button
<xpath expr="//div[@name='button_box']" position="inside">
<button name="action_view_equipment"
type="object"
class="oe_stat_button"
icon="fa-wrench">
<field name="equipment_count" widget="statinfo" string="Equipment"/>
</button>
</xpath>Modify a List View Column
<!-- Add column to sale order list -->
<xpath expr="//field[@name='amount_total']" position="before">
<field name="margin_percent" optional="show"/>
</xpath>Common Mistakes
- Wrong inherit_id — Must reference the correct parent view XML ID
- XPath matches nothing — The element was renamed or removed in a newer version. Check the parent view's current structure.
- XPath matches multiple elements — Make the expression more specific (add more attributes or path context)
- Position inside on a field — Fields don't have "inside"; use after/before instead
- Forgetting name attribute on groups/pages — Without name, other modules can't target your additions
Debugging XPath
# If your XPath doesn't work:
# 1. Find the parent view in Odoo:
# Developer Mode → Edit View → see current XML
# 2. Verify the element exists with exact attributes
# 3. Test XPath expression online (xpather.com)
# 4. Check Odoo logs for view compilation errors:
# grep -i "view\|xpath" /var/log/odoo/odoo.log | tail -20