Domain filters in Odoo 19 are among the most essential concepts in Odoo development. They define how records are restricted, searched, and managed based on specific conditions. Whether you are working with views, window actions, relational fields, or ORM operations, domains determine which data gets pulled and displayed. In Odoo 19, domain filters remain a central pillar of both development and functional configuration, providing a reliable and structured way to manage data across the entire platform.
This article walks through the fundamentals of domain filters in Odoo 19, the basic syntax, the most commonly used operators, and practical examples showing how they apply across different scenarios.
What Is a Domain in Odoo?
A domain in Odoo is essentially a structured list of conditions that filters records logically. When the ORM processes a domain, it translates those conditions into SQL queries at runtime, fetching only the relevant records in the most efficient way possible.
Domains are commonly used in the following places:
- List, form, kanban, and search views
- Window actions
- Relational fields such as Many2one, One2many, and Many2many
- Python ORM methods like
searchandsearch_read
Basic Domain Syntax
A domain is written as a list containing one or more tuples, each following this structure:
python
[('field_name', 'operator', 'value')]
A simple example:
python [('state', '=', 'done')]
This domain fetches all records where the state field holds the value 'done'.
Common Domain Operators
These are the most straightforward operators and cover standard value comparisons:
| Operator | Meaning |
|---|---|
= | Equal to |
!= | Not equal to |
> | Greater than |
< | Less than |
>= | Greater than or equal to |
<= | Less than or equal to |
Example:
Python
[('amount_total', '>', 1000)]
This retrieves records where the total amount exceeds 1000.
2. Membership Operators
Membership operators are used when you need to check whether a value exists within a defined list:
| Operator | Meaning |
|---|---|
in | Value exists in the list |
not in | Value does not exist in the list |
Example:
Python
[('state', 'in', ['draft', 'confirmed'])]
3. String Operators
String operators allow partial text matching and are particularly useful when filtering by names or descriptions:
| Operator | Meaning |
|---|---|
like | Case-sensitive partial match |
ilike | Case-insensitive partial match |
not like | Excludes records matching the text |
not ilike | Case-insensitive exclusion |
Example:
Python
[('name', 'ilike', 'invoice')]
Combining Multiple Conditions
AND: Default Behavior
When multiple tuples are placed inside a domain list without any explicit logical operator, Odoo applies AND logic by default. All conditions must be true for a record to be returned.
python
[
('state', '=', 'sale'),
('amount_total', '>', 500)
]
OR Conditions
To apply OR logic, use the pipe operator ‘|’ before the two conditions it should connect:
python
[
'|',
('state', '=', 'draft'),
('state', '=', 'confirmed')
]
Explicit AND Operator
While AND is implicit by default, it can also be written explicitly using ‘&’ for clarity or when building complex nested conditions:
python
[
'&',
('state', '=', 'sale'),
('amount_total', '>', 500)
]
Domain Filters in XML Views
Domains are heavily used inside XML view definitions, particularly with relational fields to restrict the available options.
Example 1: Restricting partner selection to companies only:
xml
<field name="partner_id"
domain="[('is_company', '=', True)]"/>
Example 2 :A dynamic domain that adapts based on the current record’s category:
xml
<field name="product_id"
domain="[('categ_id', '=', categ_id)]"/>
Here, the domain adjusts itself depending on the value of categ_id on the active record, making the filter context-aware.
Domain Filters in Window Actions
Domains can also be applied at the action level, controlling which records are visible when a menu item or button opens a view:
xml
<record id="action_sale_orders" model="ir.actions.act_window">
<field name="name">Sales Orders</field>
<field name="res_model">sale.order</field>
<field name="domain">[('state', '=', 'sale')]</field>
</record>
This ensures that when the Sales Orders action is triggered, only confirmed sale orders are shown.
Domains in Python (ORM)
In Python code, domains are passed directly into ORM methods to programmatically filter records:
python
orders = self.env['sale.order'].search([
('date_order', '>=', start_date),
('date_order', '<=', end_date)
])
This fetches all sale orders placed within a specified date range, making it a practical tool for reporting, automation, and scheduled actions.
Conclusion
Basic domain filters form the backbone of data handling in Odoo 19 development and configuration. Whether applied inside XML view definitions, window actions, or Python ORM queries, understanding how to write and combine domain conditions allows developers to build efficient, scalable, and easy-to-use business modules. Mastering this concept early on makes working with Odoo’s data layer far more intuitive and productive.