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:

how_many = model.search_count(domain)

Learn more