Add Search Option in Odoo Portal immediately boosts user experience on your Odoo 17 website. Therefore, you let customers filter records by state, sort by date or code, and search text fields in one intuitive bar. Moreover, you follow best practices by extending controllers instead of editing core code. Additionally, this guide uses active voice and transition words to keep you on track from start to finish.
Prerequisites for Portal Search Customization in Odoo 17
First, you need a working Odoo 17 environment. Next, you install or clone a custom module folder. Then, you prepare a code editor, such as VS Code or PyCharm. Finally, you ensure you have basic Python and XML skills.
Module Structure and Manifest
First, create a module folder named odoo_portal_search
. Next, add these files and folders:
odoo_portal_search/
├── __init__.py
├── __manifest__.py
├── controllers/
│ └── portal_search.py
└── views/
└── portal_templates.xml
Then, define the manifest in __manifest__.py
:
{
'name': 'Portal Search Option',
'version': '1.0',
'summary': 'Add Search Option in Odoo Portal for Odoo 17',
'category': 'Website',
'author': 'Your Name',
'website': 'https://www.yourwebsite.com',
'license': 'LGPL-3',
'depends': ['portal', 'website'],
'data': ['views/portal_templates.xml'],
'installable': True,
'application': False,
}
Step 1: Define Sort Options for Portal Search
First, you add sort‑by options so users can reorder results. Then, you map labels to database fields.
Understanding Sort Settings
First, you decide which fields users need to sort by. Next, you prepare a Python dictionary where each key represents a sort mode. Then, you reference this mapping in the controller.
Python Code Snippet for Sort Options
In controllers/portal_search.py
, begin by importing required modules:
from odoo import http, _
from odoo.http import request
from collections import OrderedDict
from odoo.osv.expression import OR
Next, define a method to return sort options:
class PortalSearchController(http.Controller):
def _get_searchbar_sortings(self):
return {
'course_date': {
'label': _('Course Date'),
'order': 'course_date desc',
},
'code': {
'label': _('Code'),
'order': 'code',
},
}
After that, you assign default sort in the route.
Step 2: Build Text Search Domain for Portal Filter
First, you create a search domain builder to let users search different fields. Then, you combine domains using OR
.
Defining the Search Domain
Next, you allow search in name and description fields. Then, you encapsulate logic in a helper method.
Python Code Snippet for Search Domain
def _get_search_domain(self, search_in, search_term):
domain_parts = []
if search_in in ('name', 'all'):
domain_parts.append(['name', 'ilike', search_term])
if search_in in ('description', 'all'):
domain_parts.append(['description', 'ilike', search_term])
return OR(domain_parts) if domain_parts else []
Furthermore, you pass search_in
and search_term
from user input.
Step 3: Implement the Portal Route and Handler
First, you define the HTTP route for portal classes or records. Next, you handle parameters: sort, filter, and search.
Setting Up HTTP Controller
Then, in the same portal_search.py
, add the route:
@http.route(
'/portal/courses',
auth='public',
website=True,
type='http'
)
def portal_courses(self,
sortby=None,
filterby=None,
search=None,
search_in='all',
**kwargs
):
# Default sort
if not sortby:
sortby = 'course_date'
searchbar_sortings = self._get_searchbar_sortings()
order_clause = searchbar_sortings[sortby]['order']
# Filter by state
states = ['draft', 'in_progress', 'completed', 'cancel']
searchbar_filters = {
'all': {'label': _('All States'), 'domain': [('state', 'in', states)]},
'draft': {'label': _('Draft'), 'domain': [('state', '=', 'draft')]},
'in_progress': {
'label': _('In Progress'),
'domain': [('state', '=', 'in_progress')],
},
# Add 'completed' and 'cancel' as needed
}
if not filterby:
filterby = 'all'
domain = searchbar_filters[filterby]['domain']
# Text search
if search:
domain += self._get_search_domain(search_in, search)
# Query records
Course = request.env['od_openacademy.course']
courses = Course.search(domain, order=order_clause)
# Prepare values for template
values = {
'courses': courses,
'searchbar_sortings': searchbar_sortings,
'sortby': sortby,
'searchbar_filters': OrderedDict(sorted(searchbar_filters.items())),
'filterby': filterby,
'search_in': search_in,
'search': search or '',
}
return request.render('portal_search.portal_courses', values)
After that, you restart Odoo, install the module, and verify the new portal route.
Step 4: Modify QWeb Template for Portal Search Bar
First, you override the existing portal template. Then, you insert HTML for the search bar.
Inheriting the Portal Template
Next, you create views/portal_templates.xml
:
<odoo>
<template id="portal_courses" inherit_id="portal.portal_my_courses">
<xpath expr="//div[@id='search_bar']" position="replace">
<div id="search_bar">
<form method="get">
<!-- Filter dropdown -->
<select name="filterby">
<t t-foreach="searchbar_filters.items()" t-as="f">
<option t-att-value="f[0]" t-att-selected="filterby==f[0]">
<t t-esc="f[1]['label']"/>
</option>
</t>
</select>
<!-- Sort dropdown -->
<select name="sortby">
<t t-foreach="searchbar_sortings.items()" t-as="s">
<option t-att-value="s[0]" t-att-selected="sortby==s[0]">
<t t-esc="s[1]['label']"/>
</option>
</t>
</select>
<!-- Search input -->
<input type="text" name="search" t-att-value="search" placeholder="Search..."/>
<select name="search_in">
<t t-foreach="searchbar_inputs.items()" t-as="i">
<option t-att-value="i[1]['input']" t-att-selected="search_in==i[1]['input']">
<t t-esc="i[1]['label']"/>
</option>
</t>
</select>
<button type="submit">Go</button>
</form>
</div>
</xpath>
</template>
</odoo>
Afterwards, you update the form action or IDs if your base template differs. Then, you refresh the portal page to see the new search bar.
Testing and Troubleshooting Your Portal Search Filter
First, you clear the browser cache to see template changes. Next, you test sort, filter, and search options one by one. Then, you check Odoo logs for errors. Finally, you adjust domain definitions if search returns unexpected results.
Common Errors and Fixes
- Error “KeyError: sortby”: Ensure your default
sortby
key matches a key in_get_searchbar_sortings()
. - Empty search results: Confirm your domain builder uses
OR
correctly and that you importedOR
fromodoo.osv.expression
. - Template not updating: Verify you installed the correct module and that your
inherit_id
matches the original QWeb template.
Advanced Tips for Odoo Portal Search Customization
First, you can enhance multi‑field search by adding more fields in _get_search_domain()
. Next, you can implement pagination by adding limit
and offset
to your .search()
call. Then, you can add AJAX‑powered live search using JavaScript and JSON routes. Moreover, you can secure the route by switching auth='public'
to auth='user'
if needed.
Adding Multi‑Field Search and Synonyms
Furthermore, you treat each search field separately. Then, you normalize user input by trimming spaces or converting to lowercase. Additionally, you use full‑text search in PostgreSQL for larger datasets. In addition, you include language‑specific stop words for global audiences.
Performance and Caching
Next, you reduce database hits by caching the course list per user session. Then, you use @http.route
options csrf=False
sparingly to improve speed. Moreover, you index commonly searched fields at the PostgreSQL level. Finally, you monitor query time using EXPLAIN ANALYZE
in psql.
Further Reading and Official Documentation
In addition, you can explore the Odoo 17 Portal Documentation for more details on portal customization. Furthermore, you can join the Odoo Forum to ask advanced questions.
Conclusion and Next Steps
First, you learned how to Add Search Option in Odoo Portal by defining sort, filter, and search domains. Next, you saw how to override the portal template to display a custom search bar. Then, you tested and troubleshot common issues. Finally, you gained tips for multi‑field search and performance. Consequently, you can now enhance your Odoo 17 portal with powerful search capabilities that improve user satisfaction.
Discover more from teguhteja.id
Subscribe to get the latest posts sent to your email.