Mastering Dynamic Domains in Odoo: Many2one & Many2many Fields Explained

December 29, 2025 by
Mastering Dynamic Domains in Odoo: Many2one & Many2many Fields Explained
Alfin Isnain Hariawan
| No comments yet

Overview

In Odoo development, dynamic domains are essential for creating smart, user-friendly forms. They allow you to filter selectable records dynamically based on other field values—preventing wrong data input and improving user experience.

This article explains how dynamic domains work in Odoo, when to use them, and how to implement them correctly for Many2one and Many2many fields using Python and XML, across modern Odoo versions (15–18).


What Is a Domain in Odoo?

A domain is a filter expression used by Odoo to limit records displayed in relational fields.

Example (static domain):

<field name="partner_id" domain="[('is_company', '=', True)]"/>

This works, but it’s static.
Dynamic domains go further by changing automatically based on user input.

Why Use Dynamic Domains?

Dynamic domains help you:

  • Prevent invalid data selection
  • Reduce user mistakes
  • Improve performance by limiting data
  • Make forms smarter and more contextual

Common use cases:

  • Filter products by category
  • Filter partners by company or subcontractor
  • Filter employees by department
  • Filter locations by warehouse


Dynamic Domain Using @api.onchange (Most Common)

Many2one Example

Scenario:
Filter partner_id based on selected subcon_id.

Python Code

@api.onchange('subcon_id')
def _onchange_subcon_id(self):
    if self.subcon_id:
        return {
            'domain': {
                'partner_id': [('id', 'in', self.subcon_id.partner_ids.ids)]
            }
        }
    else:
        return {
            'domain': {
                'partner_id': []
            }
        }

Why This Works

  • Domain updates immediately when subcon_id changes
  • No page reload required
  • Simple and reliable


Dynamic Domain for Many2many Fields

Scenario

Filter employee_ids based on selected department_id.

Python Code

@api.onchange('department_id')
def _onchange_department_id(self):
    if self.department_id:
        return {
            'domain': {
                'employee_ids': [
                    ('department_id', '=', self.department_id.id)
                ]
            }
        }

Notes

  • Domain applies to selection popup
  • Works well for large datasets
  • Avoid heavy logic inside onchange


Dynamic Domain Directly in XML

You can also define dynamic domains using field values in XML.

Example

<field name="partner_id"
       domain="[('company_id', '=', company_id)]"/>

When to Use XML Domains

  • Simple field dependency
  • No complex Python logic needed
  • Cleaner and faster

Limitation

  • Cannot use Python logic
  • Limited to field values available in the view


Using domainField Attribute in Python (Advanced)

Sometimes you want the domain to be fully dynamic and reusable.

Example

partner_id = fields.Many2one(
    'res.partner',
    domain="[('is_company', '=', True)]"
)

⚠️ This domain is evaluated client-side, not server-side.


Common Mistakes (And How to Avoid Them)

Using self incorrectly in onchange

('id', 'in', self.subcon_id.partner_ids)

✅ Correct:

('id', 'in', self.subcon_id.partner_ids.ids)


Forgetting to reset field value

When a domain changes, old values might become invalid.

Best Practice:

self.partner_id = False

Overloading onchange logic

Avoid heavy loops or database searches inside onchange.


Dynamic Domain vs Record Rules

FeatureDynamic DomainRecord Rule

UI Filtering

✅ Yes

❌ No

Security

❌ No

✅ Yes

User-specific

⚠️ Limited

✅ Yes

Performance

Fast

Medium

👉 Use domains for UX, record rules for security.


Debugging Dynamic Domains

Tips

  • Enable developer mode
  • Inspect field domain in browser
  • Log domain output temporarily
  • Test with different users

Quick Debug

import logging
_logger = logging.getLogger(__name__)
_logger.info("Domain applied: %s", domain)


Best Practices Summary

✅ Use XML domains for simple dependencies
✅ Use @api.onchange for dynamic logic
✅ Always reset dependent fields
✅ Avoid heavy computation in onchange
✅ Never rely on domains for security


Conclusion

Dynamic domains are one of the most powerful tools in Odoo form customization. When used correctly, they make your application smarter, safer, and more user-friendly—without complex JavaScript or custom widgets.

Mastering dynamic domains for Many2one and Many2many fields will significantly improve the quality of your Odoo modules.

Mastering Dynamic Domains in Odoo: Many2one & Many2many Fields Explained
Alfin Isnain Hariawan December 29, 2025
Share this post
Archive
Sign in to leave a comment