Have you ever found yourself wishing you could search for a customer in Odoo not just by their name, but also by their email address or phone number? Or perhaps you need more sophisticated control over what records appear in your relational fields, maybe even based on specific security rules or complex data relationships? If so, you’re not alone. Customizing the Odoo Many2one search functionality is a common requirement for businesses looking to streamline workflows and enhance user experience.
In this comprehensive guide, based on the mechanisms found in Odoo 19 and newer versions, we’ll dive deep into two primary methods for tailoring Many2one and Many2many field searches: the straightforward _rec_names_search attribute and the highly flexible _name_search() method. You’ll learn how to implement these customizations step-by-step, empowering your Odoo users with a more intuitive and efficient lookup experience.
For a visual walkthrough, you can also refer to this helpful tutorial: How to use _name_search() method in Odoo | Latest Odoo Tutorial.
Why Customize Odoo Many2one Search Functionality?
Relational fields like Many2one are at the heart of Odoo’s data structure, linking records across different models. By default, Odoo typically searches these fields using the _rec_name of the target model, which is often the name or a similar identifying string. While this works for basic scenarios, real-world business operations frequently demand more.
Consider these common challenges and how customizing your Odoo Many2one search can resolve them:
- Improved User Efficiency: Users spend less time hunting for records if they can use any relevant piece of information (like a phone number, product code, or email) in the search bar.
- Enhanced Data Accessibility: Unlock data that might be hidden behind a primary name, making your system more intuitive.
- Specific Business Logic: Implement complex filtering criteria that are crucial for your operations, such as showing only “active” customers or products from a specific warehouse.
- Security and Access Control: Ensure users only see records they are authorized to access, even within a lookup widget.
- Reduced Errors: Faster and more accurate lookups lead to fewer data entry mistakes and cleaner data.
Now, let’s explore the powerful tools Odoo provides to achieve this customization.
1. The Quick & Effortless Way: Customizing Odoo Many2one Search with _rec_names_search
The _rec_names_search attribute offers the fastest and simplest path to extend your Many2one search capabilities without writing intricate Python logic. It’s perfect for scenarios where you just need to add a few extra fields to the default search behavior using a simple OR condition.
Understanding the _rec_names_search Concept
- Class Attribute: This is a Python class attribute defined directly within your Odoo model.
- List of Fields: It’s a list of field names that Odoo should consider when a user types into a Many2one widget associated with that model.
- Simple OR Logic: When Odoo processes this attribute, it constructs a search domain that effectively combines the primary
_rec_namefield with all fields listed in_rec_names_searchusing anORoperator. This means if a user types “John”, Odoo will look for “John” in the_rec_namefield OR any of the fields specified in_rec_names_search.
Step-by-Step Implementation with res.partner
Let’s say your users frequently need to find customers (from the res.partner model) not just by their name, but also by their mobile phone number (mobile) or email address (email). This is a classic use case for _rec_names_search.
- Identify the Target Model: In our example, it’s
res.partner. - Inherit the Model: Create a new Python file in your custom module and inherit the
res.partnermodel. - Add the
_rec_names_searchAttribute: Define the attribute as a list containing the names of the fields you want to include in the search.
from odoo import models, fields
class ResPartner(models.Model):
_inherit = "res.partner"
# ADD THIS ATTRIBUTE TO EXTEND THE SEARCH FIELDS:
_rec_names_search = ['name', 'mobile', 'email']
# The _rec_names_search attribute is a list of Odoo fields
# that should be considered when searching records by their display name
# in Many2one or Many2many widgets.
Expected Result: After upgrading your module, when a user types “08123456789” into a Customer Many2one field, Odoo will now display partners whose name or mobile or email matches that input. This immediately enhances the user’s ability to locate records efficiently.
Benefits and Limitations of _rec_names_search
Benefits:
- Simplicity: Very easy to implement, requiring minimal code.
- Performance: Generally efficient for adding a few extra fields.
- Readability: The code clearly indicates which fields are included in the search.
Limitations:
- Basic Logic Only: Supports only simple
ORlogic between fields. You cannot implement complexANDconditions or filter by other criteria. - No Custom Domains: You can’t add security rules, custom filters, or combine search terms with other record properties.
- Field Type Dependence: Works best with text-based fields.
For more complex scenarios where you need granular control over the search logic, the _name_search() method is your go-to solution.
2. Unlocking Advanced Control: Customizing Odoo Many2one Search with _name_search()
The _name_search() method is a public ORM method that offers absolute control over how Odoo performs name-based searches. When _rec_names_search isn’t enough, _name_search() becomes indispensable for handling intricate business rules, security filters, or combining search terms with complex AND/OR logic.
Understanding the _name_search() Method Concept
- Overrideable ORM Method: This is a method that you will typically
_inheritandsuper()call to extend its default behavior. - Central Entry Point:
_name_search()is the primary method Odoo calls whenever a user types into a Many2one or Many2many field. - Full Domain Manipulation: Inside this method, you receive the user’s input (
name), existing search arguments (args), the search operator (operator), and other parameters. You can manipulate theseargsto create a custom search domain before passing it to the original_name_search()method or directly performing a search usingself._search(). - Flexibility: This method allows for sophisticated filtering, combining multiple conditions, and even integrating with external data sources if needed.
Step-by-Step Implementation with res.partner and Custom Logic
Let’s consider a more advanced scenario: you want to search for customers by Name OR Mobile Phone, but you also need to ensure that only Companies (where is_company is True) are displayed in the Many2one dropdown. This requires combining search criteria with an additional domain, which _name_search() handles perfectly.
- Identify the Target Model: Again, we’ll use
res.partner. - Inherit and Override: In your custom module, inherit
res.partnerand override the_name_searchmethod. - Define Custom Search Logic:
from odoo import models, api
class ResPartner(models.Model):
_inherit = 'res.partner'
@api.model
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
# 1. Ensure 'args' (the default domain passed to the method) is a mutable list.
# This is crucial because 'args' might be None or an immutable tuple.
args = list(args or [])
# 2. Define the primary search domain: search by name OR mobile.
# This part handles the user's input (`name`).
domain_name_or_mobile = ['|', ('name', operator, name), ('mobile', operator, name)]
# 3. Optional: Add a custom domain. For example, to only show companies.
# This is where your specific business logic comes into play.
custom_filter_domain = [('is_company', '=', True)]
# 4. Combine all the domains.
# First, add the custom filter domain to the existing arguments.
# Then, prepend the name/mobile search domain.
# The order here is important for how Odoo combines these parts.
# Combine the custom filter with existing args:
# For simplicity, let's just combine all into one 'full_domain' list.
# The 'args' parameter already contains any domain applied to the Many2one field itself.
# So we want our custom search ('domain_name_or_mobile') AND 'args' AND 'custom_filter_domain'.
# Odoo's domain system automatically ANDs lists of domains unless specified with '|' or '&'.
full_domain = domain_name_or_mobile + custom_filter_domain + args
# 5. Call the super method to execute the search with the newly constructed domain.
# This ensures Odoo's standard search mechanisms are still utilized,
# but with your custom filters applied.
return super()._name_search(
name=name, # The user's input string
args=full_domain, # Our combined domain
operator=operator, # The search operator (e.g., 'ilike')
limit=limit, # The maximum number of results
name_get_uid=name_get_uid # User ID for name_get context
)
Breaking Down the _name_search() Implementation:
args = list(args or []): This line is critical. Theargsparameter passed to_name_searchmight beNoneor an immutable tuple. By converting it to a mutable list, you can safely append or prepend your custom domain conditions.domain_name_or_mobile: This creates a domain that searches for thenameparameter in either thenamefield OR themobilefield ofres.partner. The|operator signifies an OR condition.custom_filter_domain: This is where you can add any extra, static filters you need. In our example,[('is_company', '=', True)]ensures only companies are returned.full_domain = domain_name_or_mobile + custom_filter_domain + args: This concatenates all domain parts. When domains are concatenated as lists, Odoo implicitly treats them asANDconditions. So, it will search (nameORmobile) AND (is_companyis True) AND (any existingargs).super()._name_search(...): It’s good practice to callsuper()to leverage Odoo’s default name search logic, ensuring proper handling of_rec_name, access rights, and other built-in features, while applying your custom domain.
Advanced Use Cases for _name_search()
The power of _name_search() extends far beyond simple OR logic:
- Cross-Model Search: Search for a customer based on details from a related sales order.
- Security Filtering: Implement custom access rules beyond Odoo’s record rules, perhaps based on a user’s department or role within the method.
- Complex Combinations: Use
&,|, and!operators to build highly specificAND/OR/NOTlogic. - Performance Optimization: For very large datasets, you might optimize the search query directly within
_name_search()by usingself._cr.execute()(though this should be done cautiously). - Conditional Search Logic: Dynamically alter the search domain based on the context or other fields in the form.
_rec_names_search vs. _name_search(): A Comprehensive Comparison
Choosing the right method for your Odoo Many2one search customization is crucial for maintainability and performance. Here’s an expanded comparison to help you decide:
| Feature | _rec_names_search (Attribute) |
_name_search() (Method) |
|---|---|---|
| Type | Class Attribute (List of field names) | Public ORM Method (@api.model) that you override |
| Complexity | Low (Declare a list) | High (Requires Python logic, domain manipulation) |
| Primary Function | Automatically extends Many2one search fields with simple OR logic between the primary name and listed fields. | Provides full control over the search domain, allowing complex OR/AND logic, security filters, and in-depth joins. |
| When to Use | – When you only need to add 2-3 extra fields to search quickly. – When simple OR logic between fields is sufficient. – For quick, non-critical enhancements to search. |
– When you require conditional logic or complex custom filters. – When you need to apply security rules during search. – For filtering based on related fields or computed values. – When existing Many2one domains need dynamic modification. – When combining user input with other record properties via AND. |
| Control Level | Limited to simple field inclusion. | Granular control over every aspect of the search query and domain construction. |
| Performance | Generally efficient as Odoo optimizes the underlying query. | Can be optimized or negatively impacted depending on the complexity and efficiency of your custom Python logic. |
| Maintainability | Easy to understand and maintain for basic cases. | Requires good understanding of Odoo ORM and domain syntax; potentially more complex to debug if logic is intricate. |
| Parameters | None directly; Odoo handles the integration. | Takes name, args, operator, limit, name_get_uid as parameters. |
Best Practices for Odoo Many2one Search Customization
When modifying core Odoo functionality, adhering to best practices ensures your customizations are robust, performant, and maintainable.
- Prioritize
_rec_names_searchfor Simplicity: If your requirement can be met with_rec_names_search, use it. Its simplicity reduces development time and minimizes potential for errors. - Keep
_name_search()Concise: If you must use_name_search(), try to keep its logic as focused as possible. Avoid over-complicating it, which can lead to performance issues and debugging headaches. - Test Thoroughly: Always test your Odoo Many2one search customizations with various inputs, including empty strings, partial matches, and exact matches, to ensure they behave as expected. Test performance with large datasets.
- Consider Performance: Complex
_name_search()implementations, especially those involving many joins or heavy computation, can impact performance. Profile your code if you notice slowdowns. - Use
super()Wisely: When overriding_name_search(), almost always callsuper()._name_search()to ensure that Odoo’s default logic (like access rights and existing domains) is still applied. Only omit it if you intend to completely rewrite the search mechanism. - Document Your Code: Especially for
_name_search(), clearly document why specific logic was implemented, any assumptions made, and how different domain parts are combined. - External Links & Resources: Leverage Odoo’s extensive documentation and community forums. For advanced ORM concepts that underpin these search mechanisms, refer to the Odoo developer documentation on ORM. Understanding the basics of Odoo module development will also prove invaluable.
Common Pitfalls to Avoid
- Keyword Stuffing: While we’re optimizing for
Odoo Many2one search, avoid unnaturally forcing the keyword into sentences. Focus on natural language. - Overriding
name_searchinstead of_name_search: Make sure you’re overriding the protected_name_searchmethod, not the publicname_search(which is often used to get the display names after a search). - Ignoring Existing
args: Forgetting to incorporate theargsparameter passed to_name_search()can lead to your custom filters overriding legitimate existing filters on the Many2one field. Always merge your custom domain withargs. - Performance Bottlenecks: Be cautious with
_name_search()on very large models if your custom logic involves complex computations or unindexed fields.
Conclusion: Empower Your Users with Smarter Odoo Many2one Search
Customizing the Odoo Many2one search functionality is not just a technical exercise; it’s a strategic move to significantly enhance user experience, boost productivity, and ensure data integrity within your Odoo environment. Whether you opt for the simplicity of _rec_names_search for quick wins or wield the powerful control of _name_search() for intricate business logic, Odoo provides the tools you need to tailor its core features to your exact requirements.
By understanding and applying these methods, you transform a generic search box into an intelligent, context-aware lookup tool. Start experimenting with these techniques in your Odoo 19 (or newer) instances today, and witness the immediate positive impact on your users’ daily interactions.
If you found this tutorial helpful, don’t hesitate to explore more Odoo development insights on our blog or check out the recommended video tutorial linked at the beginning of this article. Happy coding!
Discover more from teguhteja.id
Subscribe to get the latest posts sent to your email.

