In Odoo development, especially in Odoo 19, working efficiently with records and recordsets is essential. Whether you are manipulating data, creating business logic, or customizing modules, understanding how Odoo handles records can significantly improve your development skills and performance.
This blog covers everything you need to know about Records and Recordsets, including:
- Browsing Records
- Recordset Iteration
- Chained Operations
- Virtual Fields in Recordsets
- Lazy Evaluation
- Recordset Caching
What Are Records and Recordsets in Odoo?
A record is just one row of data in a model. A recordset is when you have one or more of these records together. It’s similar to how rows work in a database table.
In Odoo, methods like create() give you one record, but search() can return many records, which together make a recordset.
Example:
partner = self.env['res.partner'].browse(1) # recordset with 1 record
partners = self.env['res.partner'].search([]) # recordset with multiple records
Browsing Records
browse():
The browse() method is used to fetch records based on the IDs you provide. You pass one or more IDs to the method, and it returns the matching records from the current model.
Example:
partner = self.env['res.partner'].browse(5)
Browse Multiple IDs:
partners = self.env['res.partner'].browse([1, 2, 3])
search():
In Odoo, the search() method is used to find and get records from a model based on the conditions you give. It’s mainly used in Python code when working with Odoo models.
Example:
partners = self.env['res.partner'].search([('active', '=', True)])This returns a recordset of all active partners.
Recordset Iteration
Recordsets in Odoo can be looped through, which means you can go over each record one by one and work with them easily.
for
The standard way to iterate through a recordset is with a typical Python for loop. This lets you handle each record one at a time.
for record in self:
# Perform operations on each 'record'
print(record.name)
mapped()
The mapped() method is used to run a function or fetch a field’s value from every record in a recordset. It can return a list of values or even another recordset.
emails = partners.mapped('email')filtered()
The filtered() method gives you a new recordset that includes only the records that match a certain condition or function.
filtered_records = records.filtered(lambda r: r.company_id == user.company_id)
sorted()
The sorted() method returns a new recordset arranged in a specific order, either based on a key you provide or the model’s default sorting.
sorted_records = records.sorted(key=lambda r: r.name)
Chained Operation
Odoo allows chaining multiple methods directly on recordsets.
partners = self.env['res.partner'].search([('customer_rank', '>', 0)]).filtered(lambda r: r.email).sorted(
key=lambda r: r.name)Virtual Fields in Recordsets
In Odoo, “virtual fields” usually mean computed fields or related fields. These fields don’t exist as actual columns in the database. Instead, their values are calculated or fetched only when you access them.
Computed Fields:
These fields use a compute method, which calculates their value using other fields in the same record or from related records. They can either be saved in the database using store=True to improve performance, or they can stay fully virtual and be calculated whenever they are needed.
from odoo import models,fields,api
class TestModel(models.Model):
_name = 'test.model'
_description = 'Test Model'
quantity = fields.Integer('Quantity')
price = fields.Float('Price')
total = fields.Float('Total', compute='_compute_total', store=True) # Stored computed field
@api.depends('quantity', 'price')
def _compute_total(self):
for record in self:
record.total = record.quantity * record.price
Related Fields:
These fields get their value from another record by following a chain of related fields.
product_id = fields.Many2one('product.product', string='Product')
product_name = fields.Char(related='product_id.name', string='Product Name')Lazy Evaluation in Recordsets
Odoo recordsets use lazy evaluation, which means:
- Data is not fetched until it is needed.
- Searching or browsing does not immediately query PostgreSQL.
- Fields load only when accessed.
Recordset Caching
Once a field must be read on a given record, the ORM actually reads that field on a larger recordset and stores the returned values in cache for later use.
Prefetch Cache
When you access a field, Odoo also loads related fields that are commonly used to reduce the number of database queries.
Compute Cache
The first time a computed field is accessed, its associated compute method runs, and the resulting value is stored in the cache.
Environment Cache
Environment (env) stores frequently referenced objects to avoid repeated initialization.
Benefits of Recordset Caching
- Reduces database queries
- Improves speed significantly
- Prevents recomputation of computed fields
- Makes multiple field reads efficient
Understanding records and recordsets is important for writing clean and efficient code in Odoo 19. When you know how to use methods like search(), browse(), filtered(), mapped(), and sorted(), it becomes easier to work with data. Features such as virtual fields, lazy evaluation, and recordset caching help improve performance by avoiding unnecessary database calls. Using these techniques, you can create faster, scalable, and easy-to-maintain Odoo customizations.
To read more about How to Create Record Rules in Odoo 18, refer to our blog How to Create Record Rules in Odoo 18.