Odoo Code Snippets

Odoo is a suite of open source business apps that cover all your company needs: CRM, eCommerce, accounting, inventory, point of sale, project management, etc. Odoo apps integrate seamlessly to provide a full-featured software platform. It is a system that offers a wide range of features and functionality.

While it’s possible to use Odoo without any code snippets, you may find that certain tasks are easier if you have some coding experience. In this post, we’ve gathered a selection of useful Odoo code snippets for you to reference. Whether you’re looking to create custom reports or configure VAT settings, we’ve got something for everyone.

Odoo Code Snippets


Inherit or Modify a Search View —
<record id="account_invoice_search_extended" model="ir.ui.view">
    <field name="name">account.invoice.inherit.search</field>
    <field name="model">account.invoice</field>
    <field name="inherit_id" ref="account.view_account_invoice_filter"/>
    <field name="arch" type="xml">
        <xpath expr="//field[@name='number']" position="replace">
            <field name="number" string="Invoice" context="{'active_test': False}" filter_domain="['|','|','|','|',
            ('number','ilike',self), ('origin','ilike',self), ('reference', 'ilike', self), ('partner_id', 'child_of', self),
Create a Custom Model and Its View —
from odoo import models, fields, api, _
class Payroll(models.Model):
    _name = 'custom.payroll'
    _description = 'Payroll'

    name = fields.Char(string="Number", readonly=True, copy=False, default='New')

    state = fields.Selection([
        ('draft', 'Draft'),
        ('verify', 'Waiting'),
        ('done', 'Done'),
        ('cancel', 'Rejected'),
    ], string='Status', index=True, readonly=True, copy=False, default='draft')

    def create(self, vals):
        if vals.get('name', 'New') == 'New':
            vals['name'] = self.env['ir.sequence'].next_by_code('salary.number') or 'New'
        result = super(Payroll, self).create(vals)
        return result
Show Selection Field as Radio —
//set the widget property to radio
<field name="invoice_type" widget="radio"/>
Add Custom Fields to Product —
class ShopeeProduct(models.Model):
    _inherit = 'product.product'

    shopee_variation_id = fields.Char(string='Shopee Variation ID')

class ShopeeProductTemplate(models.Model):
    _inherit = 'product.template'

    shopee_product_id = fields.Char(string='Shopee Product ID')
Change User’s Default Page After Login —
Active developer mode under Settings
OpenSettings > Technical > User Interface > Menu Items.
Open on the Page you want to set as the landing page.
Change its Sequence to -1
Create a Wizard —
class SaleOrderWizard(models.TransientModel):
    _name = 'wizard.sale.order.download'

    def _default_orders(self):
        return self.env['sale.order'].browse(self._context.get('active_ids'))

    sale_ids = fields.Many2many('sale.order', string='Sales', default=_default_orders,
                                 auto_join=True, required=True, readonly=True)

    def download_all(self):
        if self.sale_ids:
        	for sale in self.sale_ids:
        		# Do something here
Override a Model’s Create Update and Delete Methods —
class CustomModel(models.Model):

    name = fields.Char(string='Document Name')

    def create(self, values):
        res = super(CustomModel,self).create(values)
        return res

    def write(self, values):
        res = super(CustomModel, self).write(values)
        return res

    def unlink(self, values):
        res = super(CustomModel, self).unlink()
        return res
Open Success Message Popup —
<record id="mymodule_message_wizard_form" model="ir.ui.view">
    <field name="name">mymodule.message.wizard.form</field>
    <field name="model">mymodule.message.wizard</field>
    <field name="arch" type="xml">
            <field name="message" readonly="True"/>
                <button name="action_close" string="Ok" type="object" default_focus="1" class="oe_highlight"/>
Add a Custom Field to Contact Form —
<record model="ir.ui.view" id="view_res_partner_form_inherit">
    <field name="name">module.res.partner.form.inherit</field>
    <field name="model">res.partner</field>
    <field name="inherit_id" ref="base.view_partner_form"/>
    <field name="arch" type="xml">
        <xpath expr="//field[@name='vat']" position="after">
            <field name="reference_code"/>
Change Color of Tree View’s Lines —
<tree string="Model data" decoration-danger="type_=='bimonthly'" decoration-success="name=='AA'">
    <field name="name"/>
    <field name="customer_id"/>
    <field name="type"/>
Auto Generate Name Column with Sequence —
<record id="my_model_sequence" model="ir.sequence">
    <field name="name">My Model Sequence</field>
    <field name="code">my.model</field>
    <field name="active">TRUE</field>
    <field name="prefix">TEST-</field>
    <field name="padding">4</field>
    <field name="number_next">1</field>
    <field name="number_increment">1</field>
Add Filter and Group By to Search View —
<record model="ir.ui.view" id="custom_view_product_search_form_inherit">
    <field name="name">product.template.search.form</field>
    <field name="model">product.template</field>
    <field name="inherit_id" ref="product.product_template_search_view"/>
    <field name="arch" type="xml">
        <xpath expr="//search/filter[@name='consumable']" position="after">
            <filter string="Has External Reference" name="filter_lazada" domain="[('has_external_reference','!=', '')]"/>
            <group expand="0" name="group_by" string="Group By">
                <filter name="group_product" string="Product" domain="[]"
                        context="{'group_by' : 'product_id'}"/>
Display Another Field in Many2one Instead of Name —
class ProductTemplate(models.Model):
    _inherit = 'product.template'

    def name_get(self):
        self.browse(self.ids).read(['name', 'default_code', 'description'])
        return [(template.id, '%s%s%s' % (template.default_code and '[%s] ' % template.default_code or '', template.name, template.description and ' (%s)' % template.description or ''))
                for template in self]


Set Default Date Field as Today or Any Date —
end_date = fields.Date(string='End Date', default=fields.Date.context_today, required=True)

//from external source
end_date = fields.Date(string='End Date', default=fields.Date.to_date(self._context.get('date_from')), required=false)

//any date
import time
start_date = fields.Date(string="Start Date", default=time.strftime('%Y-01-01'))


Create Email Template and Send Email Programmatically —
class MyModel(models.Model):
    _name = 'my.model'
    _description = 'My Model'

    def send_email(self):
        body_html = 'Hi {},<br/><br/>'.format(someone_name)        
        body_html += '<div>The body goes here</div>'

        email_values = {
            'email_to': '[email protected]',
            'email_from': '[email protected]',
            'body_html': body_html,
        template_id = self.env['mail.template'].search([('model', '=', 'custom.model')], limit=1)
        template_id.send_mail(template_id.id, force_send=True, email_values=email_values)

Menu & Navigation

Add a Menu Item to a Model's Navigation —
<record id="act_download_sale" model="ir.actions.act_window">
    <field name="name">Download Sales</field>
    <field name="res_model">wizard.sale.download</field>
    <field name="view_mode">form</field>
    <field name="view_id" ref="download_sale_form_view"/>
    <field name="target">new</field>

<menuitem id="menu_sale_export" parent="sale.sale_order_menu" name="Download Sales" sequence="0" action="act_download_sale"/>
Open an External URL from Menu Item —
<record model="ir.actions.act_url" id="act_open_tleapps">
    <field name="name">Tle Apps</field>
    <field name="url">https://www.tleapps.com</field>
    <field name="target">new</field>

<menuitem name="Tle Apps" id="menu_reports" parent="menu_root" action="act_open_tleapps"/>


Create a Custom QWeb Report —
<template id="custom_invoice_custom_report">
        <t t-call="web.html_container">
            <t t-foreach="docs" t-as="doc">
                <t t-call="my_module.custom_invoice_external_layout">
                    <div class="page" style="font-family: sans-serif; font-size: 15px;">
                        <div t-if="doc.name">
                            Invoice No.: <span t-field="doc.name"/>
                        <div t-if="doc.partner_id.name">
                            Partner: <span t-field="doc.partner_id.name"/>
                        <!-- Invoice lines -->
                        <t t-foreach="doc.invoice_line_ids" t-as="line">


    <!-- Layout -->
Modify Header and Footer —
<?xml version="1.0" encoding="utf-8"?>
        <template id="report_header_footer" inherit_id="web.external_layout_standard">
            <xpath expr="//div[@class='header']" position="replace">
                <div class="header">
            <xpath expr="//div[@class='footer o_standard_footer']" position="replace">
                <div class="footer o_standard_footer">


Create Settings —
<?xml version="1.0" encoding="utf-8"?>
        <record id="res_config_settings_view_form" model="ir.ui.view">
            <field name="name">res.config.settings.view.form.inherit</field>
            <field name="model">res.config.settings</field>
            <field name="priority" eval="99"/>
            <field name="inherit_id" ref="base.res_config_settings_view_form"/>
            <field name="arch" type="xml">
                <xpath expr="//div[hasclass('settings')]" position="inside">
                    <div class="app_settings_block" data-string="My Module" string="My Module"
                        <h2>My Module Settings</h2>

                        <div class="row mt16 o_settings_container">

                            <div class="col-12 col-lg-6 o_setting_box">
                                <div class="o_setting_left_pane"/>
                                <div class="o_setting_right_pane">
                                    <label string="Email From" for="custom_field"/>
                                    <div class="text-muted">Store custom data</div>
                                    <field name="custom_emails" widget="text"/>




Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top

By continuing to use the site, you agree to the use of cookies. more information

The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.