Skip to Content

Inherited Fields in Odoo: How the ORM Shares Data Across Models

A practical guide to understanding field inheritance in Odoo and how to use it in your customizations
March 6, 2026 by
Inherited Fields in Odoo: How the ORM Shares Data Across Models
Dasolo
| No comments yet

Introduction


When you start working with Odoo development, one concept comes up again and again: inheritance. Odoo's ORM is built around the idea that models can extend, share, and reuse each other's fields without duplicating data or writing redundant code.


Inherited fields are central to this system. They are how Odoo lets a model transparently access and expose fields that are physically defined and stored on another model. Once you understand this mechanism, a lot of things in the Odoo data model start making sense.


This guide explains what inherited fields are, the three types of model inheritance that produce them, how they behave in the database, and how you can use them in real Odoo customization projects.

What Is an Inherited Field in Odoo?


In Odoo's ORM framework, a field is considered inherited when a model gains access to fields defined on a different model through one of the three supported inheritance mechanisms. Instead of redefining those fields from scratch, the child model simply reuses them.


This is part of what makes the Odoo data model so compact and consistent. The same name field on a partner record is the one that shows up on sales orders, CRM leads, and invoices, because all these models eventually read from the same source.


The Three Types of Inheritance in Odoo

Odoo supports three distinct types of model inheritance, and each one handles fields differently.

1. Classical Inheritance

This is the most common pattern in Odoo development. You use _inherit without defining a new _name. This extends an existing model directly, adding new fields or methods to it. No new database table is created. The new fields simply appear on the original model.


This is how most Odoo modules add fields to standard models. If you install the CRM module, it adds fields to res.partner through classical inheritance. Those fields are stored in the partner table alongside the core fields.


2. Prototype Inheritance

This is when you combine _inherit and _name together. The new model starts as a copy of the parent model's structure, but gets its own database table. All parent fields are duplicated into the new model. Changes to the child model do not affect the parent.


This pattern is less common in everyday customization but is used to create entirely new models that share the structure of an existing one.


3. Delegation Inheritance

This is the most distinctive type, defined using _inherits. The child model links to a parent model through a Many2one field. The child model then transparently exposes all fields of the parent as if they were its own. The data lives in the parent's table, not the child's table.

This is what most developers mean when they talk about inherited fields in the strict sense. The fields are not duplicated. They are accessed through the relational link at read and write time.


The most famous example in standard Odoo is the relationship between res.users and res.partner. Every user is also a partner. The user's name, email, and phone number are stored on the partner record and accessed by the user through delegation inheritance.

How the Field Works


Delegation Inheritance Under the Hood

When a model uses _inherits, Odoo's ORM creates a transparent bridge between two database tables. When you read an inherited field on the child record, Odoo automatically follows the Many2one link to the parent record and returns the value stored there.


When you write to an inherited field from the child model, Odoo writes directly to the parent record. From the developer's perspective, the field feels native. From the database's perspective, the data lives in the parent table.


This has an important consequence: there is no data duplication. If you update a partner's name, that change immediately reflects everywhere the partner is referenced, including on the user record that inherits from it.


Classical Inheritance and the Database

With classical inheritance, new fields are added to the original model's database table. There is no second table involved. The extended model and the original model are the same thing in the database. This is the cleanest and most common way to add fields in Odoo customization projects.


Related Fields as Lightweight Inheritance

A related field is a special type of computed field in the Odoo ORM that reads a value from a linked record through a chain of relational fields. It is not strictly the same as model inheritance, but it is often used to surface inherited-style data on a model without modifying the model's structure.


For example, you might define a partner_country_id field on a sales order that reads partner_id.country_id. The field behaves like a native field on the sales order, but the value comes from the partner.

Related fields can optionally be stored in the database with store=True, which improves search and filter performance but adds storage overhead and requires recomputation when the source changes.


How Fields Are Resolved at Runtime

When Odoo loads a model definition, it resolves the full field map, including all inherited fields. By the time a model is ready for use, Odoo has already mapped every accessible field to its source, whether that source is the model's own table, a parent table via delegation, or a related chain. This resolution happens once at server startup and is cached for performance.

Business Use Cases


Inherited fields are not just a technical concept. They solve real business problems by keeping data consistent across different parts of Odoo without duplication.


1. CRM and Sales: Contact Information

When a salesperson creates a lead in the CRM module, the customer name, phone number, and email address come from the partner record via a Many2one link. If the partner's details change, every lead, quote, and order linked to that partner reflects the update immediately.


This is classical inheritance and related fields working together. The CRM module extends res.partner with CRM-specific fields (like lead count and opportunity stage), and sales orders surface partner contact info through related fields.


2. Products and Variants

Odoo's product model uses delegation inheritance to handle product variants cleanly. The product.product model (a specific variant) uses _inherits to link to product.template. Fields shared across all variants, such as product name, category, sales price, and description, live on the template. Variant-specific fields like barcode or internal reference live on the variant record itself.


This design means you can have 50 color variants of a shirt, all sharing the same name and description, without storing those values 50 times in the database.


3. Users and Partners

Every Odoo user is also a contact. The res.users model uses _inherits = {'res.partner': 'partner_id'}, which means the user automatically inherits all partner fields including name, email, phone, address, and profile picture. When you update an employee's email address, it updates in both the user settings and the contact book at the same time.


4. Inventory: Stock Moves and Product Info

Stock move lines in the Inventory module display product descriptions that come from the product template through a chain of related fields. Warehouse managers see accurate, up-to-date product information directly in their picking lists without the inventory module needing to duplicate product data.


5. Accounting: Invoice Lines

Account move lines reference products and partners. The product name, account codes, and tax configurations shown on an invoice line are surfaced from the product and partner models through relational links and related fields. Accountants see consistent data that matches what sales teams configured on the product, because they are reading from the same source.

Creating or Customizing Inherited Fields


Using Odoo Studio

Odoo Studio is the no-code interface for customizing Odoo models and views. From Studio, you can add new fields to any model without writing Python code. What Studio does under the hood is classical inheritance: it extends the model by adding a new field to its definition.


Studio also lets you create related fields. When you choose "Related Field" as the field type, you can point to any field accessible through a relational chain from the current model. For example, on the sale order model, you can create a related field that reads the customer's country or VAT number directly from the partner record.


For most business users and functional consultants, Studio is the right tool for adding fields to Odoo. It handles field naming, database migration, and view placement automatically.


Technical Customization with Python

For developers building Odoo modules, inherited fields are defined in Python using the models.Model class from the Odoo ORM.


Classical inheritance to add a custom field to an existing model:

class CrmLead(models.Model):
    _inherit = 'crm.lead'

    x_contract_value = fields.Float(
        string='Estimated Contract Value'
    )

Delegation inheritance to create a new model that shares fields from an existing one:

class EmployeeProfile(models.Model):
    _name = 'hr.employee.profile'
    _inherits = {'res.partner': 'partner_id'}

    partner_id = fields.Many2one(
        'res.partner',
        required=True,
        ondelete='cascade'
    )
    employee_id = fields.Many2one(
        'hr.employee',
        string='Employee'
    )

Related fields to surface a value from a linked record:

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

    partner_country_id = fields.Many2one(
        related='partner_id.country_id',
        string='Customer Country',
        store=True
    )

Via XML-RPC API (Remote Configuration)

Fields can also be added programmatically using Odoo's XML-RPC API and the ir.model.fields model. This is the approach used in Dasolo's remote config notebooks. It is equivalent to what Studio does, and it allows field creation without direct server access.


To add a related field via the API, you create an ir.model.fields record with ttype='many2one' (or the appropriate type) and set the related parameter to define the relational path. This approach is well-suited for deploying custom fields as part of an automated setup process.

Best Practices


Choose the Right Inheritance Type for the Job

Use classical inheritance when you simply want to add fields or methods to an existing model. It is the simplest approach and is what the vast majority of Odoo modules use. Reserve delegation inheritance for cases where you genuinely need two separate record sets linked together, such as when a business concept extends a contact without being a contact itself.


Prefer Related Fields for Read Access

If you only need to display a value from a linked record on a form or list view, a related field is cleaner than delegation inheritance. It avoids creating a new structural dependency and is easy to understand and maintain.


Be Careful with store=True on Related Fields

Storing a related field in the database speeds up searches and filters, but it means the value is a copy. Odoo triggers recomputation when the source changes, but in edge cases this can fall out of sync. Only store related fields when you genuinely need to filter or sort by them at scale.


Always Prefix Custom Fields with x_

Any field you add to a standard Odoo model through inheritance should start with x_ (or use a module namespace in a proper module). This prevents conflicts with fields added by Odoo in future versions.


Document Your Inheritance Chain

When working on complex customizations, write a brief comment or design note explaining where fields come from and why. A field named x_country_code on a sale order might not obviously link back to partner_id.country_id.code without documentation.


Handle Cascade Deletes Correctly

In delegation inheritance, the parent record is created automatically when the child is created. When the child is deleted, the parent should usually be deleted too. Set ondelete='cascade' on the Many2one in _inherits to ensure clean deletion without orphaned records.


Common Pitfalls


Confusing the Three Inheritance Types

The most common mistake for developers new to Odoo is using _inherit with _name when they intended classical extension. This accidentally creates a brand new model instead of extending the existing one. Double-check your model definition: if you do not intend to create a new model, omit _name.


Forgetting to Create the Parent Record in _inherits

With delegation inheritance, the parent record does not create itself automatically in all scenarios. When creating a child record programmatically via the API or in a script, you need to either let Odoo's ORM handle the parent creation (which it does when you use create normally) or create the parent record first and pass its ID. Skipping this step results in a database constraint error.


Trying to Change a Field's Type Through Inheritance

Odoo does not allow overriding the type of an existing field via inheritance. You can change attributes like the string label, domain, or help text, but you cannot change a Char field to an Integer field. Attempting this will cause a module installation error.


Overusing Stored Related Fields

Adding store=True to every related field is tempting for performance reasons, but it increases database size and introduces maintenance overhead. If the source field changes frequently, stored related fields trigger a lot of recomputation. Use stored related fields selectively, only when you have a concrete need to filter or group by them in large datasets.


Assuming Inherited Fields Respect Child Model Access Rules

Fields inherited via delegation live on the parent model. Access rights defined on the child model do not automatically apply to those fields at the database level. If you restrict access to the child model but not the parent, users may still be able to read the inherited field values through the parent model directly. Always review security rules for both models when using delegation inheritance.

Conclusion


Inherited fields are not a niche feature of Odoo development. They are baked into the architecture of the system. The relationship between users and partners, between product variants and templates, between sale orders and customer contact info: all of these rely on field inheritance to keep data consistent and avoid duplication.


Understanding which inheritance type to use, when to use a related field instead, and how these mechanisms behave in the database will make you a significantly more effective Odoo customizer. You will write cleaner code, design better data models, and spend less time debugging unexpected field behavior.


The key takeaway is simple: Odoo's ORM is designed so that fields live in one place and are accessed from many. This is the principle behind inherited fields, and it is what keeps Odoo's data model coherent even as it grows across dozens of interconnected modules.

Need Help with Your Odoo Implementation?


At Dasolo, we help companies implement, customize, and optimize Odoo. Whether you are building a custom module from scratch, extending standard models with new fields, or trying to understand why your data model behaves in unexpected ways, our team has the hands-on Odoo experience to help you move faster and avoid costly mistakes.


If you have questions about your Odoo data model, custom field strategy, or technical implementation, we would be happy to talk through your situation. Reach out to us and let's find the right approach for your project.

Inherited Fields in Odoo: How the ORM Shares Data Across Models
Dasolo March 6, 2026
Share this post
Sign in to leave a comment