Have you ever stopped to think about what makes Odoo models so adaptable and efficient? If you're already building with Odoo or just beginning to explore it, getting familiar with model attributes is a game-changer. In Odoo 19, these attributes act like the foundation of your business logic—they control how information is stored, how the system reacts, and even how records appear and behave in the interface. Understanding them gives you the keys to really shape and customize your applications.
You can think of model attributes as the instructions that guide Odoo on how to treat your data. They define whether information gets stored in the database, kept in memory for quick processing, or used as a base structure for other models to inherit from. This flexible system is a big part of what makes Odoo such a powerful and customizable platform for building business applications.
The Three Pillars of Odoo Models
Before diving into the extensive list of attributes, let's understand the three fundamental types of models that form the foundation of every Odoo application:
1. Model - The Workhorses of Your Application
Regular database-persisted models are the bread and butter of Odoo applications. These models represent your core business entities like customers, products, sales orders, and invoices. Every record created from these models is permanently stored in the database and persists across sessions. When you create a customer record or generate an invoice, you're working with a Model.
Use Case: Customer records, product catalog, sales orders, accounting entries – essentially any data that needs to be permanently stored and retrieved.
# -*- coding: utf-8 -*-
class LibraryBook(models.Model):
_name = 'library.book' # Unique technical name of the model
_description = 'Library Book Management' # Human-readable name
_table = 'library_book' # Custom table name (optional)
_rec_name = 'name' # Field used as display name
_order = 'name asc' # Default sorting order
_inherit = [] # Inherit from existing models (if needed)
_inherits = {} # Delegation inheritance (parent_model: field_id)
_abstract = False # Set True if it's an abstract model
_transient = False # Set True for wizard (temporary model)
_auto = True # Auto-create database table
_register = True # Register model in ORM
_parent_name = 'parent_id' # Field for hierarchical relation
_parent_store = False # Enable tree structure optimization
_active_name = 'active' # Field used for archive/unarchive
_check_company_auto = True # Enforce multi-company consistency
_allow_sudo_commands = True # Allow sudo operations on this model
_rec_names_search = ['name', 'isbn'] # Fields used for search in many2one
# SQL view related (used only if _auto = False)
_table_query = None # Define SQL query for view-based models
_depends = {} # Dependencies for SQL view models
# Fields
name = fields.Char(string="Book Name", required=True)
isbn = fields.Char(string="ISBN")
author = fields.Char(string="Author")
active = fields.Boolean(string="Active", default=True)
parent_id = fields.Many2one(
'library.book',
string="Parent Book",
ondelete='cascade'
)
2. TransientModel - The Temporary Helpers
TransientModels are designed for temporary data that serves a specific purpose and then gracefully exits the stage. These models store data in the database but come with a built-in self-destruct mechanism – the system automatically cleans up old records to prevent database bloat. They're perfect for wizards, temporary calculations, and user interaction forms.
Use Case: Wizard forms, temporary reports, data import/export helpers, user preference dialogs that don't need permanent storage.
# -*- coding: utf-8 -*-
class BookReportWizard(models.TransientModel):
_name = 'library.book.report.wizard' # Unique model name
_description = 'Book Report Generation Wizard' # Display name
_table = 'library_book_report_wizard' # Optional custom table
_rec_name = 'name' # Display field in UI
_order = 'id desc' # Default sorting
_inherit = [] # Classical inheritance (rare in wizards)
_inherits = {} # Delegation inheritance (not recommended here)
_abstract = False # Not abstract
_transient = True # Marks as transient model
_auto = True # Auto-create table
_register = True # Register in ORM
_transient_max_count = 1000 # Max number of records to keep
_transient_max_hours = 1.0 # Auto-delete records older than X hours
_parent_name = None # Not used in wizards
_parent_store = False # No hierarchy
_active_name = 'active' # Optional archive support
_check_company_auto = False # Usually not required
_allow_sudo_commands = True # Allow sudo operations
_rec_names_search = ['name'] # Search fields
# SQL-related (not used in transient models)
_table_query = None
_depends = {}
# Fields
name = fields.Char(string="Wizard Name")
date_from = fields.Date(string="Start Date")
date_to = fields.Date(string="End Date")
active = fields.Boolean(string="Active", default=True)
3. AbstractModel - The Blueprint Masters
AbstractModels play a key role when it comes to reusing code efficiently. They don’t generate their own database tables; instead, they act as a base structure that other models build upon. You can think of them as reusable components that offer shared fields, methods, and behavior, helping multiple models access the same functionality without rewriting it each time.
Use Case: Common functionality like mail threading, website publishing features, or any shared behavior that multiple models need to implement.
# -*- coding: utf-8 -*-
class TimestampMixin(models.AbstractModel):
_name = 'timestamp.mixin' # Unique technical name
_description = 'Timestamp Mixin for Common Date Fields' # Display name
_table = None # No table created for abstract models
_rec_name = None # Usually not needed in abstract models
_order = None # No default ordering (not used directly)
_inherit = [] # Can inherit other mixins if needed
_inherits = {} # Delegation inheritance (rare in abstract)
_abstract = True # Marks this as abstract model
_transient = False # Not a transient model
_auto = False # No database table created
_register = True # Registered so it can be inherited
_parent_name = None # No hierarchy
_parent_store = False # No tree optimization
_active_name = None # No archive concept here
_check_company_auto = False # Not needed in mixins
_allow_sudo_commands = True # Allow sudo by default
_rec_names_search = [] # Not used
# SQL-related (not applicable)
_table_query = None
_depends = {}
# Common reusable fields
created_on = fields.Datetime(
string="Created On",
default=fields.Datetime.now
)
updated_on = fields.Datetime(
string="Last Updated On"
)
The Complete Arsenal of Model Attributes
Now that we understand the model types, let's explore the comprehensive set of attributes that give you precise control over your model's behavior:
Core Identity Attributes
_name (str): The unique identifier of your model in dot-notation. This is like your model's passport – it must be unique across the entire Odoo ecosystem. Example: 'sale.order', 'res.partner', 'product.template'.
_description (str | None): The human-readable name of your model that appears in user interfaces, menus, and error messages. While optional, it's essential for user experience. Example: 'Sales Order', 'Customer', 'Product Template'.
_module (str | None): Indicates which Odoo module this model belongs to. This helps with module dependencies and organization. Usually set automatically by the framework.
_custom (bool): A flag that should be set to True only for custom models created through Odoo's Studio or custom development. It helps distinguish between core Odoo models and custom extensions.
Database and Table Management
_auto (bool): Controls whether Odoo automatically creates a database table for this model. Set to False if you want to create the table manually or use a database view. Automatically defaults to True for abstract models.
_table (str): Specifies the exact SQL table name to use in the database. If not set, Odoo automatically generates it from the model name by replacing dots with underscores.
_table_query (SQL | str | None): Allows you to define the model's content as an SQL expression, essentially creating a database view instead of a regular table. Perfect for complex reporting models.
_table_objects (dict[str, TableObject]): Advanced attribute for defining SQL/Table objects associated with the model. Used for complex database operations and optimizations.
Model Behavior Flags
_register (bool): Controls whether the model should be registered in Odoo's model registry and become visible to the framework. Set to False for utility classes that shouldn't be instantiated as models.
_abstract (bool): Marks the model as abstract. Abstract models don't create database tables and are meant to be inherited by other models to share common functionality.
_transient (bool): Designates the model as transient, meaning its records are automatically cleaned up by the system after a certain period. Perfect for temporary data and wizards.
Inheritance and Composition
_inherit (str | list[str] | tuple[str, ...]): Defines Python-style inheritance. If _name is set, these are parent models to inherit from. If _name is unset, it extends an existing model in-place, adding new fields and methods.
_inherits (frozendict[str, str]): Implements composition-based inheritance using a dictionary mapping parent model names to foreign key field names. The new model exposes all parent fields but stores them in the linked records.
_inherit_children (OrderedSet[str]): Automatically maintained set of child models that inherit from this model. Used internally by the framework for inheritance resolution.
User Interface and Display
_rec_name (str | None): The field used for displaying records in selection lists, many2one fields, and breadcrumbs. Defaults to 'name' if that field exists, otherwise uses the first field.
_rec_names_search (list[str] | None): List of fields to search when users type in many2one fields or use the global search. Enhances user experience by making records findable through multiple fields.
_order (str): Default ordering for records when no specific order is requested. Uses SQL ORDER BY syntax. Example: 'name asc', 'create_date desc, name'.
_fold_name (str): Field name used to determine whether groups should be folded in kanban views. Usually a boolean field that controls the collapsed/expanded state of kanban columns.
Hierarchical Structure
_parent_name (str): The many2one field that creates parent-child relationships between records of the same model. Enables hierarchical structures like organization charts or category trees.
_parent_store (bool): Enables optimized storage for hierarchical data by computing a parent_path field. This dramatically improves performance of child_of and parent_of domain operations on large hierarchical datasets.
Active Records Management
_active_name (str | None): Automatically set to either 'active' or 'x_active' to identify the field used for archiving/unarchiving records. Active records appear in normal views while archived ones are hidden but not deleted.
Localization and Translation
_translate (bool): Controls whether fields in this model are included in translation exports. While still functional, this is considered legacy and may be deprecated in future versions.
Security and Access Control
_check_company_auto (bool): Automatically validates company consistency on relational fields marked with check_company=True. Prevents data leaks between different companies in multi-company setups.
_allow_sudo_commands (bool): Controls whether One2many and Many2many commands can target this model when using sudo() or with_user(). Security-sensitive models should set this to False to prevent privilege escalation attacks.
Advanced Performance Optimization
_depends (frozendict[str, Iterable[str]]): Defines dependencies for models backed by SQL views, specifying which model fields trigger updates. Format: {model_name: field_names}. Used for cache invalidation and database synchronization.
Extension In Odoo 19
class SaleOrder(models.Model):
"""
This class extends the existing `sale.order` model to add a custom test field.
Technical Notes:
- Uses classical inheritance (_inherit)
- Does not create a new model, only extends existing one
"""
_inherit = 'sale.order' # Extending existing model
test_field = fields.Char(
string="Test Field",
help="This is a test field.",
)
Delegation In Odoo 19
class LibraryBook(models.Model):
"""
This model demonstrates delegation inheritance using `_inherits`
with `product.template`.
Key Concept:
- `_inherits` links models via Many2one
- Fields of parent model are accessible directly
- Data is stored in multiple tables
"""
_name = 'library.book'
_description = 'Library Book using product.template'
_inherits = {
'product.template': 'product_tmpl_id'
}
product_tmpl_id = fields.Many2one(
'product.template',
string="Related Product",
required=True,
ondelete='cascade',
help="Links this book to a product template record."
)
author = fields.Char(
string="Author",
help="Name of the book author.",
required=True,
index=True,
)
isbn = fields.Char(
string="ISBN",
help="Unique identifier for the book.",
copy=False,
index=True,
)
Classical inheritance
class Inheritance0(models.Model):
_name = 'inheritance.0'
_description = 'Inheritance Zero'
name = fields.Char()
def call(self):
return self.check("model 0")
def check(self, s):
return "This is {} record {}".format(s, self.name)
class Inheritance1(models.Model):
_name = 'inheritance.1'
_inherit = ['inheritance.0']
_description = 'Inheritance One'
def call(self):
return self.check("model 1")
Putting It All Together
Understanding these attributes empowers you to create models that are not just functional, but optimized, secure, and user-friendly. Each attribute serves a specific purpose in the grand architecture of your Odoo application, from the basic _name that gives your model identity, to the advanced _depends that optimizes performance in complex scenarios.
In Odoo 19, model attributes go well beyond basic configuration. They’re what turn ordinary Python classes into fully functional business components. Whether you're adding a simple custom field or designing a complex setup across multiple companies, understanding these attributes gives you the control and flexibility needed to build reliable and scalable solutions.
As you grow in your Odoo development experience, keep in mind that these attributes are more than just technical details — they’re the foundation of how real business processes take shape in the system. Behind every smooth Odoo rollout, whether for a small company or a large organization, sits a careful and intentional use of these model attributes.
To read more about An Overview of Model Attributes in Odoo 18, refer to our blog An Overview of Model Attributes in Odoo 18.