Reading data from Odoo
Querying Odoo models with search_read - domains, field lists and paging through large result sets.
The workhorse of Odoo's external API is search_read - it filters a model with a domain, returns only the fields you ask for and pages through large result sets with limit and offset. This chapter uses the Odoo.Sample connection defined in the main Odoo chapter.
Domains and field lists
A domain is a list of conditions, each a tuple of field name, operator and value. The example below reads customers from a given city, returning only the fields the integration actually needs:
# -*- coding: utf-8 -*-
# Zato
from zato.server.service import Service
class GetCustomers(Service):
name = 'demo.odoo.get-customers'
input = 'city'
def handle(self) -> 'None':
# Connection to use
conn_name = 'Odoo.Sample'
# Obtain a client connected to the system
with self.outgoing.odoo.get(conn_name).conn.client() as client:
# Point the client to the model we want to query
model = client.get_model('res.partner')
# Customers from the input city only
domain = [
('customer_rank', '>', 0),
('city', '=', self.request.input.city),
]
# Fields to retrieve
fields = ['name', 'email', 'phone', 'street']
# Read the matching records
customers = model.search_read(domain, fields)
# Return them to the caller
self.response.payload = {'customers': customers}
Each record arrives as a regular Python dict, with the id field always included:
{'id': 42, 'name': 'Deco Addict', 'email': 'deco.addict82@example.com',
'phone': '(603)-996-3829', 'street': '325 Elsie Drive'}
Paging through large sets
Large models are read page by page - limit caps the size of each page and offset skips the records already processed:
# How many records to read per page
page_size = 200
# Where the current page starts
offset = 0
while True:
# Read one page of records
records = model.search_read(domain, fields, offset=offset, limit=page_size)
# An empty page means the whole result set is exhausted
if not records:
break
# Process the current page
for record in records:
self.logger.info('Received -> %s', record['name'])
# Move on to the next page
offset += page_size
To learn only how many records match, without transferring any of them, use search_count: