Skip to content

Odoo Inheritance Types: _inherit vs _inherits vs _name Explained

DeployMonkey Team · March 22, 2026 12 min read

Why Three Types?

Odoo has three inheritance mechanisms, each serving a different purpose. Confusing them is one of the most common mistakes new developers make. Here is exactly when and how to use each.

Type 1: Extension Inheritance (Most Common)

Add fields or methods to an existing model without creating a new table.

class ResPartner(models.Model):
    _inherit = 'res.partner'  # Extend existing model
    # NO _name — same model, same table

    loyalty_points = fields.Integer(string='Loyalty Points', default=0)
    membership_tier = fields.Selection([
        ('bronze', 'Bronze'),
        ('silver', 'Silver'),
        ('gold', 'Gold'),
    ], string='Tier')

    def compute_tier(self):
        for partner in self:
            if partner.loyalty_points >= 1000:
                partner.membership_tier = 'gold'
            elif partner.loyalty_points >= 500:
                partner.membership_tier = 'silver'
            else:
                partner.membership_tier = 'bronze'

What Happens

  • No new database table — columns added to res_partner
  • All existing res.partner records gain the new fields
  • Existing methods still work
  • You can override existing methods (call super())

Use When

You want to add fields or behavior to an existing Odoo model. This is 90% of customization work.

Type 2: Delegation Inheritance (_inherits)

Create a new model that automatically includes all fields from another model via a required Many2one link.

class Student(models.Model):
    _name = 'school.student'
    _inherits = {'res.partner': 'partner_id'}  # Delegation

    partner_id = fields.Many2one(
        'res.partner', required=True, ondelete='cascade',
    )
    student_id = fields.Char(string='Student ID')
    grade = fields.Selection([...])
    enrollment_date = fields.Date()

What Happens

  • New table: school_student (with student-specific fields)
  • Each student record has a linked res.partner record
  • When you read student.name, it reads from the linked partner
  • When you write student.name = 'Alice', it writes to the partner
  • Creating a student auto-creates a partner (or links existing)

Use When

You want a new model that "is a" special version of an existing model. Student is a partner. Employee is a partner. The new model has all partner fields plus its own fields.

Standard Odoo Examples

# res.users _inherits res.partner
# → Every user IS a partner (has name, email, phone)
# → User adds: login, password, groups

# product.product _inherits product.template
# → Every variant IS a template (has name, price)
# → Variant adds: specific attributes, barcode

Type 3: Prototype Inheritance (_inherit + _name)

Create a completely new model that copies the structure of an existing model.

class MailBlacklist(models.Model):
    _name = 'my.blacklist'
    _inherit = 'mail.thread'  # Copy structure, NOT extend
    _description = 'My Blacklist'

    # Gets all fields and methods from mail.thread
    # but in a completely separate table: my_blacklist

What Happens

  • New table: my_blacklist
  • All fields and methods from mail.thread are copied
  • Changes to your model do NOT affect mail.thread
  • Changes to mail.thread do NOT affect your model

Use When

You want to create a new model with the same structure as an existing one. Rare in practice — mostly used with abstract models like mail.thread and mail.activity.mixin.

Abstract Models

class MailThread(models.AbstractModel):
    _name = 'mail.thread'
    # AbstractModel — no database table
    # Designed to be inherited via prototype inheritance

class SaleOrder(models.Model):
    _name = 'sale.order'
    _inherit = ['mail.thread', 'mail.activity.mixin']
    # Gets chatter and activities — these are prototype inherits
    # from abstract models

Comparison Table

AspectExtensionDelegationPrototype
Syntax_inherit = 'model'_inherits = {'model': 'field'}_name = 'new'
_inherit = 'model'
New table?NoYesYes
New model?NoYesYes
Modifies original?YesNoNo
Frequency90% of casesRareWith abstract models

Common Mistakes

  • Adding _name when you meant to extend — Creates a new model instead of extending the existing one
  • Using _inherits when _inherit is enough — Unnecessary complexity and extra table
  • Forgetting super() in method overrides — Breaks the original method's behavior
  • Multiple _inherit (list)_inherit = ['mail.thread', 'mail.activity.mixin'] is prototype inherit from multiple abstract models, not extension of multiple models