Enable Dark Mode!
overview-of-read-orm-method-in-odoo-19.jpg
By: Sidharth P

Overview Of Read() ORM Method in Odoo 19

Technical Odoo 19 Odoo Enterprises Odoo Community

One of the core ORM methods in Odoo for obtaining data from the database is the read() method. Without loading extraneous data, it gives developers an effective method to retrieve particular field values from records. Building effective Odoo applications and maximising performance require an understanding of the read() method.

What is the Read() Method?

Field values are retrieved from one or more records in a model using the read() method. Each dictionary in the list of dictionaries it returns represents a record with field names acting as keys and matching values. In contrast to other retrieval techniques, read() offers a simple method of accessing data in the format of a plain Python dictionary.

Syntax:

records.read(fields=None, load='_classic_read')

Parameters:

  • fields: A list of the names of the fields to be returned. All fields are retrieved if None or not specified.
  • load: Manages relational fields' loading mode. '_classic_read' is the default. To prevent loading the display_name of Many2one fields, set it to None.

Returns: A list of dictionaries, one dictionary per record, that map field names to their values.

Raises:

  • AccessError: if the requested information is not accessible to the user.
  • ValueError: if a field that is requested is not present.

Reading All Fields

The read() method retrieves every field defined in the model when the fields parameter is either None or not specified. When you need full record information, this is helpful, but it should be used carefully to prevent performance problems.

partner = self.env['res.partner'].browse(1)
complete_data = partner.read()
# Result includes all fields:
# [{'id': 1, 'name': 'John Doe', 'email': 'john@example.com',
#   'phone': '123456', 'street': '123 Main St', ...}]

For models with numerous fields or computed fields, reading every field can be inefficient even though it is convenient. For improved performance, think about defining just the fields you require.

Reading Specific Fields

The read() method's ability to precisely specify the fields you require is one of its main benefits. This greatly lowers database load and boosts performance, particularly for models with a large number of fields or computed fields.

Example: Reading Selected Fields

partners = self.env['res.partner'].search([('customer_rank', '>', 0)], limit=5)
partner_data = partners.read(['name', 'email', 'phone'])
# Result:
# [
#     {'id': 1, 'name': 'John Doe', 'email': 'john@example.com', 'phone': '123456'},
#     {'id': 2, 'name': 'Jane Smith', 'email': 'jane@example.com', 'phone': '789012'},
#     ...
# ]

Observe that even when it isn't specifically requested, the 'id' field is always included in the outcome. This guarantees the uniqueness of every dictionary.

Understanding Field Access Control

The read() function upholds field-level access rights and complies with Odoo's security model. An AccessError is raised when a user tries to read fields that they are not authorised to access.

Example: Handling Access Errors

from odoo.exceptions import AccessError
try:
   sensitive_data = partner.read(['name', 'bank_ids'])
except AccessError as e:
   # Handle the case where user doesn't have access
   print(f"Access denied: {e}")
   # Fallback to reading only permitted fields
   safe_data = partner.read(['name', 'email'])

Sensitive data is safeguarded in accordance with the set access rights and record rules thanks to this security feature.

Validating Field Names

The read() method verifies that the model contains all requested fields. A ValueError is raised when you try to read a field that doesn't exist.

Example: Handling Invalid Fields

try:
   data = partner.read(['name', 'nonexistent_field'])
except ValueError as e:
   print(f"Invalid field requested: {e}")
   # Read only valid fields
   data = partner.read(['name', 'email'])

By identifying typos and mistakes early in the development process, this validation helps avoid unexpected behaviour or silent failures.

Working with Relational Fields

Relational fields are handled differently by the read() method based on the load parameter and the type of field. For efficient data processing, it is essential to comprehend these behaviours.

Many2one Fields with Default Load

Many2one fields are typically returned as a tuple with the ID and display name of the associated record.

order = self.env['sale.order'].browse(1)
order_data = order.read(['name', 'partner_id'])
# Result:
# [{'id': 1, 'name': 'SO001', 'partner_id': (5, 'John Doe')}]

The related record can be easily displayed in user interfaces without the need for extra queries thanks to the tuple format (id, display_name).

Many2one Fields with load=None

When the load parameter is set to None, display names for Many2one fields are not automatically loaded; only the ID is returned.

order_data = order.read(['name', 'partner_id'], load=None)
# Result:
# [{'id': 1, 'name': 'SO001', 'partner_id': 5}]

When you want to avoid the overhead of loading display names and only require the ID for additional processing, this option is helpful.

One2many and Many2many Fields

Regardless of the load parameter, the One2many and Many2many fields return a list of the related records' IDs.

partner = self.env['res.partner'].browse(1)
partner_data = partner.read(['name', 'child_ids', 'category_id'])
# Result:
# [{
#     'id': 1,
#     'name': 'ABC Company',
#     'child_ids': [10, 11, 12],
#     'category_id': [2, 5]
# }]

You would need to carry out additional read operations on those IDs in order to obtain comprehensive information about these related records.

Reading Data from Multiple Records

In a single call, the read() method effectively manages several records. It returns a list with one dictionary per record when called on a recordset with several records.

Example: Batch Reading

partners = self.env['res.partner'].search(
   [('country_id.code', '=', 'US')], limit=100)
partner_list = partners.read(['name', 'email', 'city', 'state_id'])
# Returns a list of dictionaries
for partner_dict in partner_list:
   print(
       f"Partner: {partner_dict['name']}, City: {partner_dict['city']}")

Because it reduces database queries and overhead, this batch approach is more efficient than reading records one at a time in a loop.

Reading from Empty Recordsets

Empty recordsets are handled gracefully by the read() method, which returns an empty list without generating errors.

# Search that returns no results
partners = self.env['res.partner'].search(
   [('name', '=', 'NonExistentName')])
# read() on empty recordset returns empty list
data = partners.read(['name', 'email'])
print(data)  # []

In most situations, this behaviour makes it safe to perform read operations and chain searches without the need for extra empty checks.

The Read-Only Nature of read()

The @api.readonly decoration on the read() method indicates that it is a high-level function that should not be overridden. It does not alter records; its sole purpose is data retrieval.

Odoo offers lower-level functions like _fetch_query() and _read_format() that can be overridden in custom modules if you need to alter how data is retrieved from the database or formatted.

Performance Considerations

The read() function is designed to efficiently retrieve data. You can, however, make better choices regarding data retrieval in your applications if you comprehend how it operates.

Specify Only Required Fields

Instead of reading every field, always specify the ones you need. This speeds up operations and lessens database load.

# Efficient - reads only needed fields
data = partners.read(['name', 'email'])
# Less efficient - reads all fields including computed ones
data = partners.read()

Use load=None When Appropriate

Use load=None to avoid computing the display names of Many2one fields if you don't need them.

# Faster when display names aren't needed
data = orders.read(['partner_id', 'amount_total'], load=None)

Batch Operations

It is more efficient to read several records in one call as opposed to reading each one separately in a loop.

# Efficient - single read call
all_data = partners.read(['name', 'email'])
# Inefficient - multiple read calls
all_data = []
for partner in partners:
   all_data.extend(partner.read(['name', 'email']))

One effective and potent tool for retrieving data in Odoo 19 is the read() ORM method. It offers a lightweight method of accessing database data while adhering to security controls and field validations by returning field values as Python dictionaries. Developers can optimize data retrieval for various scenarios by comprehending the parameters, particularly the fields list and load parameter. The read() method provides the performance and flexibility required for professional Odoo development, whether reading individual records or batch processing large datasets. Building effective, maintainable applications that manage data retrieval requires mastery of this technique.

To read more about Overview Of Search_read() ORM Method in Odoo 19, refer to our blog Overview Of Search_read() ORM Method in Odoo 19.



Frequently Asked Questions

What does Odoo 19's read() method accomplish?

Field values can be retrieved as simple Python dictionaries from one or more records using the read() method. It offers a structured, safe, and effective method of accessing database data without loading extraneous fields or objects.

Do read() results always include the id field?

Sure. To uniquely identify every record in the returned dictionary, Odoo always includes the id field in the result, even if it is not specifically requested.

What occurs if I ask for a field that doesn't exist?

If you try to read a field that isn't defined on the model, Odoo raises a ValueError. This aids in the early detection of typos and invalid field references during development.

How are relational fields like Many2one and One2many handled by read()?

By default, many2one fields are returned as (id, display_name) tuples; if load=None is used, only the id is returned. A list of related record IDs is always returned by the One2many and Many2many fields.

Does the read() method adhere to record rules and access rights?

Indeed. Odoo's security model is fully respected by the read() method. An AccessError is raised if the current user is not authorized to access a field or record.

How can I use read() more efficiently?

Use load=None when display names are not required, read multiple records in a single call rather than looping through individual records, and always specify only the required fields for improved performance.

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



0
Comments



Leave a comment



whatsapp_icon
location

Calicut

Cybrosys Technologies Pvt. Ltd.
Neospace, Kinfra Techno Park
Kakkancherry, 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