Reader small image

You're reading from  Odoo 15 Development Essentials - Fifth Edition

Product typeBook
Published inFeb 2022
Reading LevelBeginner
PublisherPackt
ISBN-139781800200067
Edition5th Edition
Languages
Tools
Right arrow
Author (1)
Daniel Reis
Daniel Reis
author image
Daniel Reis

Daniel Reis has a degree in applied mathematics and an MBA. He has had a long career in the IT industry, mostly as a consultant implementing business applications in a variety of sectors. He has been working with Odoo (OpenERP at the time) since 2010 and is an active contributor to the Odoo Community Association (OCA), where he also serves as a board member. He is the managing director of Open Source Integrators, a leading open source and Odoo consultancy firm.
Read more about Daniel Reis

Right arrow

Chapter 7: Recordsets – Working with Model Data

In the previous chapters, we gave an overview of model creation and loading data into models. Now that we have a data model and some data to work with, it's time to learn more about how to programmatically interact with it.

A business application needs business logic to compute data, perform validations, or automate operations. The Odoo framework API provides the tools for a developer to implement this business logic. Most of the time, this means querying, transforming, and writing data.

Odoo implements an Object-Relational Mapping (ORM) layer on top of the lower level database. The ORM objects provide the Application Programming Interface (API) to be used to interact with the data. This API provides an execution environment and the creation of recordsets, that are objects used to work the data stored in the database.

This chapter explains how to use the execution environment and recordsets so that you have all the...

Technical requirements

The code examples in this chapter will be executed in an interactive shell and do not require any code from the previous chapters. A copy of the code can be found in the GitHub repository for this book (https://github.com/PacktPublishing/Odoo-15-Development-Essentials) in the ch07/ch07_recorsets_code.py file.

Using the shell command

Python includes a command-line interface that is a great way to explore the language. Odoo includes a similar feature through the shell command option. These commands can be executed interactively to better understand how they work.

To use it, add the shell command when starting Odoo, plus any Odoo options that we would usually use when starting Odoo:

(env15) $ odoo shell -c library.conf

This will initiate the usual server startup sequence in the terminal, but instead of launching an HTTP server listening for requests, it will start a Python prompt waiting for input.

This interactive command interface simulates the environment found inside a class method, running under the OdooBot superuser. The self variable is available and is set to the OdooBot superuser record object.

For example, these commands inspect the self recordset:

>>> self
res.users(1,)
>>> self._name
'res.users'
>>> self.name
'OdooBot...

The execution environment

Odoo recordsets operate in an environment context, providing relevant information about the context where the operation was triggered. For example, the database cursor being used, the current Odoo user, and more.

Python code running inside a model method has access to the self recordset variable, and the local environment can be accessed with self.env. The server shell environment also provides a self reference in a similar way to what is found inside a method.

In this section, we will learn about the attributes made available by the execution environment and how to use them.

Environment attributes

As we have seen, self is a recordset. Recordsets carry environment information with them such as the user browsing the data and additional context-related information (for example, the active language and time zone).

The current environment can be accessed using the env attribute of a recordset, as shown in this example:

>>> self.env...

Querying data with recordsets and domains

Odoo business logic will need to read data from the database to perform actions based on it. This is done through recordsets, which query the raw data and expose it as Python objects we can manipulate.

Odoo Python will usually be running in a class method, where self represents the recordset to work with. In some cases, we need to create recordsets for other models. For that, we should get a reference to the models and then query it to create the recordset.

The environment object, usually accessible as self.env, holds references to all the models available, and these can be accessed using dictionary-like syntax. For example, to get a reference to the partner model, use self.env['res.partner'] or self.env.get('res.partner'). This model reference can then be used to create recordsets, as we will see next.

Creating recordsets

The search() method takes a domain expression and returns a recordset with the records...

Accessing data in recordsets

Once we have a recordset, we want to inspect the data contained in it. So, in the following sections, we will explore how to access data in recordsets.

We can get field values for individual records called singletons. Relational fields have special properties, and we can use dot-notation to navigate through linked records. Finally, we will discuss some considerations for when we need to handle date and time records and convert them between different formats.

Accessing individual record data

When a recordset has only one record it is called a singleton. Singletons are still recordsets and can be used wherever a recordset is expected.

But unlike multi-element recordsets, singletons can access their fields using dot-notation, as follows:

>>> print(self.name)
OdooBot

In the next example, we can see that the same self singleton recordset also behaves as a recordset, and we can iterate it. It has only one record, so only one name is...

Writing to records

We have two different ways to write to records: using the object-style direct assignment or using the write() method. The write() method is the low-level method in charge of performing write operations, and it is still used directly when using the external API or when loading XML records. The object-style direct assignment was added later into the ORM model. It implements the active record pattern and can be used in Python code logic.

Changes in Odoo 13

In Odoo 13, the ORM model introduced a new database writing approach called in-memory ORM. In previous Odoo versions, every write would immediately generate the corresponding database SQL command, and this came with a performance penalty, especially when complex interdependencies caused repeated updates on the same records. Since Odoo 13, these operations are instead saved in a memory cache, and at the end of the transaction, the new flush() method is automatically called to perform the corresponding database...

Working with date and time fields

In the Accessing data in recordsets section, we saw how to read date and time values from records. It is common to also need to perform date calculations and to convert dates between their native format and string representations. Here, we will see how to perform these kinds of operations.

Odoo provides a few useful functions to create new date and time objects.

The odoo.fields.Date object provides these helper functions:

  • The fields.Date.today() function returns a string with the current date in the format expected by the server, using UTC as a reference. This is adequate to compute default values. It can be used directly in a date field definition by using default=fields.Date.today.
  • The fields.Date.context_today(record, timestamp=None) function returns a string with the current date in the session's context. The time zone value is taken from the record's context. The optional timestamp parameter is a datetime object and...

Working with recordsets

A recordset is a collection of records, and Python business logic frequently needs to use them. There are several operations that can be performed on recordsets, such as mapping and filtering. We can also compose new recordsets by adding or removing records. Other common operations are inspecting the contents of a recordset to check if a particular record is there or not, for example.

Changes in Odoo 10

Since Odoo 10, recordset manipulation has preserved the record order. This is unlike previous Odoo versions, where recordset manipulation was not guaranteed to preserve the record order, although addition and slicing maintained the record order.

Recordset operations

Recordsets have a few functions available to perform useful actions on them, such as sorting or filtering records.

These are the supported functions and attributes:

  • The recordset.ids attribute returns a list with the IDs of the recordset elements.
  • The recordset.ensure_one...

Transactions and low-level SQL

ORM methods that are called from a client run in a transaction. Transactions ensure correctness in the case of concurrent writes or failures. During a transaction, the data records used are locked, protecting them from other concurrent transactions and ensuring that they are not unexpectedly changed. In case of failure, all the transaction changes are rolled back, returning to the initial state.

Transaction support is provided by the PostgreSQL database. When an ORM method is called from a client, a new transaction is initiated. If an error occurs during the method execution, any changes that have been made are reverted. If the method execution completes with no errors, then the changes made are committed, making them effective and visible to all other transactions.

This is automatically handled for us, and we usually don't need to worry about it. However, in some advanced use cases, it might be useful to have control over the current transaction...

Summary

In this chapter, we learned how to work with model data to perform CRUD operations—that is, creating, reading, updating, and deleting data—and all the techniques needed to make use of and manipulate recordsets. This provides the foundation needed for us to implement our business logic and automation code.

To experiment with the ORM API, we used the Odoo interactive shell. We ran our commands in an environment accessible through self.env. The environment is similar to the one provided in the model method, and so it is a useful playground for exploring the Odoo API.

The environment allows us to query data from any Odoo model that is made available as a recordset. We learned about the different ways to create recordsets and then how to read the data provided, including special data types such as dates, binary values, and relational fields.

Another fundamental capability in Odoo is to write back data. In this chapter, we also learned how to create new records...

Further reading

The official Odoo documentation for recordsets can be found at https://www.odoo.com/documentation/15.0/developer/reference/backend/orm.html.

lock icon
The rest of the chapter is locked
You have been reading a chapter from
Odoo 15 Development Essentials - Fifth Edition
Published in: Feb 2022Publisher: PacktISBN-13: 9781800200067
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
undefined
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime

Author (1)

author image
Daniel Reis

Daniel Reis has a degree in applied mathematics and an MBA. He has had a long career in the IT industry, mostly as a consultant implementing business applications in a variety of sectors. He has been working with Odoo (OpenERP at the time) since 2010 and is an active contributor to the Odoo Community Association (OCA), where he also serves as a board member. He is the managing director of Open Source Integrators, a leading open source and Odoo consultancy firm.
Read more about Daniel Reis