Searching for records is also a common operation in business logic methods. This recipe shows how to find all the Partner
companies and their contacts by company name.
This recipe will be using the same simplified res.partner
definition as the Creating new records recipe previously. You may refer to this simplified definition to know the fields.
We will write the code in a method called find_partners_and_contact(self, name)
.
In order to find the partners, you need to perform the following steps:
res.partner
:@api.model def find_partners_and_contacts(self, name): partner = self.env['res.partner']
domain = ['|', '&', ('is_company', '=', True), ('name', 'like', name), '&', ('is_company', '=', False), ('parent_id.name', 'like', name) ]
search()
method with the domain and return the recordset:return partner.search(domain)
Step 1 defines the method. Since we are not using the contents of self
, we decorate it with @api.model
, but this is not linked to the purpose of this recipe. Then, we get an empty recordset for the res.partner
model because we need it to search res.partner
records.
Step 2 creates a search domain in a local variable. Often you'll see this creation inlined in the call to search, but with complex domains, it is a good practice to define it separately.
For a full explanation of the search domain syntax, please refer to the Defining filters on record lists: Domain recipe in Chapter 8, Backend Views.
Step 3 calls the
search()
method with the domain. The method returns a recordset containing all records matching the domain, which can then be further processed. In the recipe, we call the method with just the domain, but the following keyword arguments are also supported:
offset=N
: This is used to skip the N
first records that match the query. This can be used together with limit
to implement pagination or to reduce memory consumption when processing a very large number of records. It defaults to 0
.limit=N
: return at most N
records. By default, there is no limit.order=sort_specification
: This is used to force the order on the returned recordset. By default, the order is given by the _order
attribute of the model class.count=boolean
: If True
, this returns the number of records instead of the recordset. It defaults to False
.We said that the search()
method returned all the records matching the domain. This is not completely true. The method ensures that only records to which the user performing the search has access are returned. Additionally, if the model has a boolean
field called active and no term of the search domain is specifying a condition on that field, then an implicit condition is added by search to only return active=True
records. So if you expect a search to return something but you only get empty recordsets, be sure to check the value of the active
field (if present) and to check for record rules.
See the recipe Calling a method with a different context in Chapter 6, Advanced Server Side Development Techniques for a way to not have the implicit active = True
condition added. See the Limit record access using record rules recipe in Chapter 10, Accessing Security for more information about record level access rules.
If for some reason you find yourself writing raw SQL queries to find record IDs, be sure to use self.env['
record.model
'].search([('id', 'in', tuple(ids)).ids
after retrieving the IDs to make sure that security rules are applied. This is especially important in multicompany Odoo instances where record rules are used to ensure proper discrimination between companies.
3.138.172.82