ODOO: Model Inheritance in Odoo

Odoo inheritance allows developers to extend and customize existing modules without modifying the original source code. This post covers the four inheritance mechanisms — Classical, Extension, Prototype, and Delegation — with practical examples of when and how to use each.

One of the most powerful features of Odoo as a development platform is its inheritance system. Rather than modifying the original Odoo source code (which would break on every upgrade), developers create new modules that extend existing ones through inheritance.

This keeps your customizations maintainable, isolated, and upgrade-safe.


Why Inheritance Matters

Odoo is an ERP platform with hundreds of built-in modules developed over many years. When you need to customize a feature — adding a field to a sales order, changing a method's behavior, or reusing a model's structure — you should never edit the core files directly.

Instead, Odoo provides inheritance mechanisms that let your module hook into existing models, views, and methods cleanly.

md
+---------------------------+
|      Original Module      |
|      (e.g., sale)         |
|   SaleOrder model         |
|   name, partner, lines    |
+---------------------------+
           |
           | _inherit
           v
+---------------------------+
|     Your Custom Module    |
|   Extended SaleOrder      |
|   + x_custom_field        |
|   + custom logic          |
+---------------------------+


The Four Inheritance Types

TypeKey AttributeCreates New TablePurpose
Classical_name + _inheritYesNew model that copies from existing
Extension_inherit onlyNoExtend existing model in-place
Prototype_name + _inheritsYesNew model that delegates to existing
Delegation_inheritsYesComposition via delegation

1. Classical Inheritance

Classical inheritance creates a new model that inherits fields and behavior from an existing model. The new model gets its own database table and is a separate entity.

python
from odoo import models, fields

class ProductTemplate(models.Model):
    _name = 'product.template'
    _inherit = 'product.template'

    x_custom_field = fields.Char(string="Custom Field")

When to use it

Use Classical Inheritance when you want to create a new model that shares some structure with an existing model but is otherwise independent.

md
product.template (original)
    name, price, description
         |
         | Classical Inheritance
         v
product.template (your extension)
    name, price, description  (copied)
    x_custom_field            (added)


2. Extension Inheritance

Extension inheritance is the most commonly used inheritance type in Odoo. It extends an existing model by adding new fields, methods, or modifying existing behavior — without creating a new table.

The extended model continues to exist with the same name (_name is NOT redefined). The original table is modified to include the new fields.

python
from odoo import models, fields

class SaleOrder(models.Model):
    _inherit = 'sale.order'

    x_custom_field = fields.Char(string="Custom Field")

    def action_confirm(self):
        super(SaleOrder, self).action_confirm()
        # Custom logic runs after the original confirmation
        for order in self:
            order.x_custom_field = 'Confirmed'

Key Points

  • _inherit is set but _name is not redefined
  • The model keeps its original name and table
  • New fields are added as columns to the existing table
  • Methods can be overridden with super() to call the original implementation

Calling the Parent Method

Always call super() when overriding CRUD methods or action methods, unless you intentionally want to replace the entire behavior:

python
def write(self, vals):
    # Pre-processing
    result = super(SaleOrder, self).write(vals)
    # Post-processing
    return result

When to use it

This is your go-to inheritance type for customizing existing Odoo modules — adding fields to sales orders, modifying partner logic, extending invoice behavior, etc.

md
sale.order (original Odoo module)
    partner_id, order_lines, amount_total
         |
         | Extension (_inherit only)
         |
    sale.order (now includes your additions)
    partner_id, order_lines, amount_total
    x_custom_field                          ← added by you


3. Prototype Inheritance

Prototype inheritance creates a new model that uses another model's fields via a Many2one link but adds its own fields and behavior on top.

The new model has a _name (its own table) and uses _inherits (not _inherit) to delegate fields from the linked model.

python
from odoo import models, fields

class NewPartner(models.Model):
    _name = 'new.partner'
    _inherits = {'res.partner': 'partner_id'}

    partner_id = fields.Many2one(
        'res.partner',
        required=True,
        ondelete='cascade'
    )
    x_custom_field = fields.Char(string="Custom Field")

How It Works

md
new.partner table
    id | partner_id (FK) | x_custom_field
    1  |      42         |  "VIP"

res.partner table
    id | name       | email
    42 | "Amr"      | "amr@example.com"

When you access new_partner.name, Odoo transparently delegates the lookup to the linked res.partner record.

When to use it

Use Prototype Inheritance when you need to create a specialized version of an existing entity with additional attributes, while still reusing all the original entity's fields and behavior.


4. Delegation Inheritance

Delegation inheritance is structurally similar to Prototype Inheritance — it uses _inherits to delegate fields to another model via a Many2one relationship. The difference is conceptual: Delegation is used for composition rather than specialization.

python
from odoo import models, fields

class PartnerExtension(models.Model):
    _name = 'partner.extension'
    _inherits = {'res.partner': 'partner_id'}

    partner_id = fields.Many2one(
        'res.partner',
        required=True,
        ondelete='cascade'
    )
    x_custom_field = fields.Char(string="Custom Field")

`_inherit` vs `_inherits`

AttributeTypeCreates TableDelegates
_inherit (string)Extension InheritanceNoNo
_inherit (string) + _nameClassical InheritanceYesNo
_inherits (dict)Delegation/PrototypeYesYes

Overriding Views with Inheritance

Inheritance in Odoo applies not just to models but also to views (the XML UI definitions). You can extend an existing view to add, remove, or modify fields without touching the original XML.

xml
<odoo>
    <record id="view_order_form_inherit_custom" model="ir.ui.view">
        <field name="name">sale.order.form.inherit.custom</field>
        <field name="model">sale.order</field>
        <field name="inherit_id" ref="sale.view_order_form"/>
        <field name="arch" type="xml">
            <!-- Add a new field inside the sheet -->
            <sheet position="inside">
                <group>
                    <field name="x_custom_field"/>
                </group>
            </sheet>
        </field>
    </record>
</odoo>

View Inheritance Positions

PositionDescription
insideInsert content inside the matched element
beforeInsert content before the matched element
afterInsert content after the matched element
replaceReplace the matched element entirely
attributesModify the matched element's attributes

Best Practices for Odoo Inheritance

Always use a custom module — never modify the original Odoo source files.

Use Extension Inheritance by default — it is the most common and cleanest approach for adding fields and methods.

Always call super() when overriding methods unless you intentionally want to skip the original logic.

Prefix custom fields with x_ — this is the Odoo convention for custom fields to avoid naming conflicts with future Odoo updates.

Keep modules focused — each custom module should extend one specific area of functionality, making it easier to maintain and upgrade.

md
Good Module Design:
    custom_sale_features/     ← sale-specific customizations
    custom_stock_features/    ← stock-specific customizations
    custom_partner_fields/    ← partner-specific customizations

Avoid:
    big_customization_module/ ← everything mixed together


Inheritance Decision Guide

md
What do you need to do?
        |
        +-- Add fields or methods to an existing model?
        |         --> Extension Inheritance (_inherit only)
        |
        +-- Create a brand new model based on an existing one?
        |         --> Classical Inheritance (_name + _inherit)
        |
        +-- Create a specialized model that reuses all fields
        |   from another model?
        |         --> Prototype / Delegation (_inherits)
        |
        +-- Share common fields/logic across multiple models?
                  --> Abstract Model (models.AbstractModel)


Final Thoughts

Odoo's inheritance system is one of its greatest strengths as a development platform. It enables a clean separation between the core product and your customizations, ensuring that your work survives Odoo version upgrades with minimal rework.

Mastering these four inheritance types — Classical, Extension, Prototype, and Delegation — gives you the full toolkit to customize any part of Odoo without compromising the integrity of the original modules.

Customize everything. Break nothing. Upgrade safely.