Enable Dark Mode!
how-to-use-model-attributes-in-odoo-19.jpg
By: Swaraj R

How to Use Model Attributes in Odoo 19

Technical Odoo 19 Odoo Enterprises Odoo Community

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.


Frequently Asked Questions

What are model attributes in Odoo?

Model attributes are special properties defined in a model class that control how the model behaves—how data is stored, displayed, secured, and processed in Odoo.

Why are model attributes important?

They define the core behavior of your model, including database storage, UI representation, security rules.

What are the main types of models in Odoo 19?

There are three types, Model (models.Model), TransientModel, AbstractModel.

When should I use a normal Model?

Use it when you need permanent data storage, such as Customers, Products, Sales orders, Invoices.

When should I use a TransientModel?

Use it for temporary operations, such as wizards, reports, import/export tools.

What is an AbstractModel used for?

It is used for code reuse, adding common fields like created_on, updated_on across multiple models.

If you need any assistance in odoo, we are online, please chat with us.



0
Comments



Leave a comment



Recent Posts

whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, KINFRA Techno Park
Kakkanchery, Calicut
Kerala, India - 673635

location

Kochi

Cybrosys Technologies Pvt. Ltd.
1st Floor, Thapasya Building,
Infopark, Kakkanad,
Kochi, India - 682030.

location

Bangalore

Cybrosys Techno Solutions
The Estate, 8th Floor,
Dickenson Road,
Bangalore, India - 560042

Send Us A Message