Custom Smart Buttons in Odoo 18 boost your user experience by showing real‑time record counts and opening filtered action windows. TheOdoo 18 Cron Jobs: Automate Scheduled Tasksrefore, you can track related sales orders directly from product forms. Additionally, you can extend this technique to any model, and thus you gain more navigation power. Moreover, this tutorial targets both developers and business users who want a step‑by‑step guide. For more details, see the official Odoo 18 documentation.
Overview of Odoo 18 Custom Smart Buttons
First, we explain what Odoo 18 custom smart buttons do. Basically, smart buttons appear at the top of form views and they show a count of related records. Then, when users click the button, Odoo opens a filtered list or kanban view. Consequently, users navigate faster without digging menus. This guide walks you through creating smart buttons on the product form that count sales orders. In addition, you learn how to open those orders in an action window.
Prerequisites and Environment Setup
Before we code, ensure that you meet these requirements:
- Odoo 18 Community or Enterprise installed locally.
- Python 3.8+ and pip installed.
- PostgreSQL running and a demo database created.
- VS Code, PyCharm, or any code editor ready.
- Basic knowledge of Odoo module structure and XML.
Next, we set up a custom add‑ons folder. For example:
mkdir -p ~/odoo/custom_addons/odoo_smart_buttons
cd ~/odoo/custom_addons/odoo_smart_buttons
Then, we configure Odoo to load that path:
# in odoo.conf
addons_path = /usr/lib/python3/dist-packages/odoo/addons,~/odoo/custom_addons
Module Structure for Smart Buttons
We organize our module as follows:
odoo_smart_buttons/
│
├── __init__.py
├── __manifest__.py
│
├── models/
│ ├── __init__.py
│ └── product.py
│
└── views/
└── product_form_view.xml
Create Module Folder
Firstly, create the module folder:
mkdir -p models views
touch __init__.py
Add Manifest File
Secondly, add __manifest__.py with these contents:
{
'name': 'Odoo 18 Smart Buttons',
'version': '1.0',
'category': 'Sales',
'summary': 'Add custom smart buttons with record count and action window',
'description': """
Custom Smart Buttons in Odoo 18 let you show related record counts
and open action windows. This module adds a sales order count button
to the product form.
""",
'author': 'YourName',
'website': 'https://www.yourdomain.com',
'depends': ['sale', 'product'],
'data': [
'views/product_form_view.xml',
],
'installable': True,
'application': False,
'license': 'LGPL-3',
}
We set installable to True and application to False because this module adds a small feature, not a full app.
Python Model Definition
We extend the product.template model to compute a sales order count.
Define Computed Field and Method
In models/product.py, write:
from odoo import api, fields, models
class ProductTemplate(models.Model):
_inherit = 'product.template'
sale_order_count = fields.Integer(
string='Sales Order Count',
compute='_compute_sale_order_count',
store=False
)
def _compute_sale_order_count(self):
for product in self:
# Count sale.order lines that include this product
order_lines = self.env['sale.order.line'].search([
('product_id', '=', product.product_variant_id.id)
])
product.sale_order_count = len(order_lines)
Explain Python Code
- We import
api,fields, andmodelsfrom Odoo. - We inherit
product.template. - We define
sale_order_countas an integer field, computed on the fly. - We implement
_compute_sale_order_countmethod. It searchessale.order.linefor the current variant. - We assign the length of found records to the field.
Using active voice, we keep our code clear. Then, we proceed to view configuration.
XML View Configuration
We add a smart button in views/product_form_view.xml:
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<record id="view_product_form_smart_button" model="ir.ui.view">
<field name="name">product.form.smart.button</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="arch" type="xml">
<!-- Place button next to existing smart buttons -->
<xpath expr="//header" position="inside">
<button name="action_open_sale_orders"
type="object"
class="oe_stat_button"
icon="fa-shopping-cart">
<field name="sale_order_count" widget="statinfo" string="Orders"/>
</button>
</xpath>
</field>
</record>
</odoo>
Insert Custom Smart Button
We locate the <header> in the product form and insert:
<button>tag with:name="action_open_sale_orders": calls a Python method.type="object": triggers Python code.class="oe_stat_button": uses built‑in style.icon="fa-shopping-cart": shows a cart icon.
Use XML Attributes and XPath
We use an xpath expression that matches the form’s header. Then, we insert our button. Consequently, we avoid breaking the original view.
Style the Button
We rely on Odoo’s oe_stat_button class. However, if you want a colored label or a different layout, you can override CSS in static/src/css/style.css:
.oe_stat_button .fa-shopping-cart {
color: #2a8fbd;
}
Then add 'static/src/css/style.css' to manifest data or assets.
Filtered Action Window
Users click the button and see sales orders filtered to the current product.
Define Action in XML
We add this action in the same XML file below our view:
<record id="action_product_sale_orders" model="ir.actions.act_window">
<field name="name">Product Sales</field>
<field name="res_model">sale.order</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('order_line.product_id', '=', active_id)]</field>
<field name="context">{'default_product_id': active_id}</field>
</record>
Explain Action Window
- We set
view_modeto show list and form views. - We use
domainto filter orders whose lines include the product. - We pass
contextso that new records default to this product.
Python Method to Open Action
We add a Python method in models/product.py:
def action_open_sale_orders(self):
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'name': 'Sales Orders',
'res_model': 'sale.order',
'view_mode': 'tree,form',
'domain': [('order_line.product_id', '=', self.product_variant_id.id)],
'context': {'default_product_id': self.id},
}
This method returns the action we defined or inline action. Active voice and transition words guide the reader.
Testing and Validation
- Restart Odoo server and update your module:
./odoo-bin -d your_db -u odoo_smart_buttons
- Log in, go to Sales → Products, open any product.
- You see the new smart button with a number.
- Click it. Then, Odoo shows related sales orders.
As a tip, clear cache if you don’t see updates.
Customization Tips and Best Practices
Use Shorter Words
Therefore, keep method names concise. For example, use action_open_sale instead of action_open_sales_order_lines.
Keep Active Voice
Furthermore, write methods that return clear dicts. For instance, we return actions directly.
Distribute Keyphrase Evenly
We repeat “custom smart buttons in Odoo 18” and synonyms like “Odoo 18 smart buttons” to boost SEO.
Add Outgoing Link
Finally, you can link to the Odoo community forum to find more examples.
Conclusion
In summary, we built a module that adds custom smart buttons in Odoo 18. First, we extended the model to compute record counts. Next, we defined smart buttons in XML and wrote a Python method to open filtered action windows. Then, we tested and validated our work. Moreover, we shared best practices and tips. Consequently, you now know how to implement custom smart buttons that enhance navigation and data visibility. You can apply these steps to any model and any related records. Enjoy faster workflows and a more intuitive UI!
Feel free to explore further by checking the official Odoo 18 tutorial series or asking questions on the Odoo forum.
Discover more from teguhteja.id
Subscribe to get the latest posts sent to your email.

