How To Use Odoo Abstract Models for Reusable Module Features

March 10, 2026 by
How To Use Odoo Abstract Models for Reusable Module Features
Jasson
| No comments yet

When building Odoo modules, you'll often find yourself repeating the same fields or methods across multiple models — things like audit timestamps, approval workflows, or status tracking. Abstract models let you define this logic once and reuse it everywhere, keeping your code DRY and maintainable.


What is an Abstract Model?

In Odoo, there are three types of models:

  • models.Model — A regular model stored in the database
  • models.TransientModel — A temporary model (used in wizards)
  • models.AbstractModel — A blueprint model, not stored in the database

Abstract models are never instantiated on their own. They exist purely to be inherited by other models, sharing their fields and methods without creating a database table.


A Simple Example: Adding Audit Fields

Say you want every model in your app to track who created a record and when it was last updated. Instead of adding fields to each model, define an abstract model:

from odoo import models, fields

class AuditMixin(models.AbstractModel):
    _name = 'mixin.audit'
    _description = 'Audit Mixin'

    created_by = fields.Char(string='Created By', readonly=True)
    last_updated = fields.Datetime(string='Last Updated', readonly=True)

    def write(self, vals):
        vals['last_updated'] = fields.Datetime.now()
        return super().write(vals)

    def create(self, vals):
        vals['created_by'] = self.env.user.name
        return super().create(vals)

class ApprovalMixin(models.AbstractModel):
    _name = 'mixin.approval'
    _description = 'Approval Workflow Mixin'

    state = fields.Selection([
        ('draft', 'Draft'),
        ('submitted', 'Submitted'),
        ('approved', 'Approved'),
        ('rejected', 'Rejected'),
    ], string='Status', default='draft')

    def action_submit(self):
        self.state = 'submitted'

    def action_approve(self):
        self.state = 'approved'

    def action_reject(self):
        self.state = 'rejected'

Now, any model can inherit this mixin:

from odoo import models

class SaleOrderCustom(models.Model):
    _name = 'sale.order.custom'
    _inherit = ['mixin.audit']
    _description = 'Custom Sale Order'

That's it. Your sale.order.custom model now automatically has created_by, last_updated, and the override logic — no copy-pasting needed.


Using Multiple Mixins

One of the best parts? You can stack multiple abstract models using _inherit as a list:

class ExpenseClaim(models.Model):
    _name = 'hr.expense.claim'
    _inherit = ['mixin.audit', 'mixin.approval']
    _description = 'Expense Claim'


Summary

Abstract models are one of Odoo's most underused features. They let you write shared logic once and compose it across many models cleanly. Start small — extract just one repeated pattern into a mixin — and you'll quickly see how much cleaner your codebase becomes.


 

How To Use Odoo Abstract Models for Reusable Module Features
Jasson March 10, 2026
Share this post
Archive
Sign in to leave a comment