A record set is a collection of related items or records. When
working with a single record or a record set of length 1, accessing
any field value is straightforward. However, when dealing with
multiple records, you cannot directly access a field value by simply
using the field name. If you attempt to use the dot notation (e.g.,
self.partner_id.name) on a record set containing more than one
record, an error will occur.
For example, consider the res.partner model, which holds all the
contact records in an Odoo database. If the variable partner
contains a single res.partner record, you can easily access the
contact's name using partner.name. However, if partner contains
multiple records, direct field access like this is not possible.
In such cases, Odoo provides the mapped() method, which allows you to
efficiently traverse and access field values across a record set
containing multiple records.
Let’s go through an example to understand this process in detail.
from odoo import fields, models
class StudentStudent(models.Model):
_name = "student.student"
_description = "Student"
name = fields.Char(string="Name", required=True)
phone = fields.Char(string="Phone Number")
email = fields.Char(string="Email")
partner_id = fields.Many2one('res.partner', string="Partner", required=True)
date = fields.Date(string="Date", default=fields.Date.today())
parent_id = fields.Many2one('student.parent', string="Parent")
from odoo import fields, models
class StudentParent(models.Model):
_name = "student.parent"
_description = "Parent"
name = fields.Char(string="Name", required=True)
phone = fields.Char(string="Phone Number")
email = fields.Char(string="Email")
partner_id = fields.Many2one('res.partner', string="Partner", required=True)
date = fields.Date(string="Date", default=fields.Date.today())
student_ids = fields.Many2many('student.student', string="Students")
The Parent model includes a relational field called
student_ids, which stores all students associated with that parent.
If the student_ids field contains a single student record, you can
directly access the student's name using student_ids.name. However,
if student_ids contains multiple student records, direct access in
this way is not possible.
To retrieve the names of all associated students, we can define a
method called get_student_name(). In this method, the mapped()
function can be used to efficiently extract all student names from
the student.student recordset.
def _get_students_name(self, parents):
names = parents.mapped('student_ids.name')
In this scenario, the mapped(path) method iterates over the fields of
a recordset, where path is a string representing the field
name, and nested fields can be accessed using dot notation. The
mapped() method returns either a new recordset or a list containing
all the values that correspond to the specified path for each record
in the current recordset.
At each level of the provided path, mapped() builds an intermediate
recordset. For example, when using student_ids.name, the mapped()
method first retrieves all student_ids and then collects the name
field from each related student record.
In this case, the variable names will store a Python list of all
student names.
- When the path points to a relational field, mapped() returns a
recordset.
- When the path refers to a basic field type (such as Char,
Integer, etc.), mapped() returns a Python list of values.
Although mapped() is a powerful and convenient method, it is not
always the most performance-efficient choice. This is because it
operates in memory within the Odoo server and may trigger multiple
SQL queries when traversing relational fields. In such cases, it is
generally better to use the search() method with an appropriate
domain to optimize query performance.