Skip to content

Snippets ​

Insert Odoo fields, decorators, methods, views, buttons and menus by typing a snippet prefix in a Python or XML file.

Odoo snippet suggestions in a PyCharm XML file and a Python file, each with a description

What you can do ​

All prefixes start with odoo. Type odoo in a Python or XML file to see the list of snippets with their descriptions. Select one, or type the full prefix, and press Enter to insert it. Replace the placeholder values after the snippet is inserted.

For snippets that create views, actions, menus or security records, the plugin uses the model of your current context to fill in model names and record IDs where it can.

Get started ​

  1. Open a Python or XML file in your Odoo module.
  2. Type odoo and select a snippet.
  3. Edit the placeholders.

Python snippets ​

Fields ​

PrefixDescriptionInserts
odoo_field_booleanCreate Boolean fieldfields.Boolean(string='Active')
odoo_field_charCreate Char fieldfields.Char(string='Name')
odoo_field_textCreate Text fieldfields.Text(string='Description')
odoo_field_floatCreate Float fieldfields.Float(string='Amount', digits=(16, 2))
odoo_field_integerCreate Integer fieldfields.Integer(string='Quantity')
odoo_field_dateCreate Date fieldfields.Date(string='Start Date')
odoo_field_datetimeCreate Datetime fieldfields.Datetime(string='Timestamp')
odoo_field_many2oneCreate Many2one fieldfields.Many2one('model.name', string='Partner', ondelete='restrict')
odoo_field_one2manyCreate One2many fieldfields.One2many('model.name', 'inverse_field_name', string='Order Lines')
odoo_field_many2manyCreate Many2many fieldfields.Many2many('model.name', string='Tags')
odoo_field_htmlCreate HTML fieldfields.Html(sanitize=True, string='Content')
odoo_field_binaryCreate Binary fieldfields.Binary(attachment=True, string='File')
odoo_field_selectionCreate Selection fieldSee below
python
fields.Selection([
    ('draft', 'Draft'),
    ('done', 'Done')
], string='Status', default='draft')

API decorators ​

PrefixDescriptionInserts
odoo_api_create_multiAdd model_create_multi decorator@api.model_create_multi
odoo_api_dependsAdd depends decorator@api.depends('field_name')
odoo_api_onchangeAdd onchange decorator@api.onchange('field_name')
odoo_api_constrainsAdd constrains decorator@api.constrains('field_name')
odoo_api_returnsAdd returns decorator@api.returns('model.name')

Imports ​

PrefixDescriptionInserts
odoo_import_fieldsImport fieldsfrom odoo import fields
odoo_import_modelsImport modelsfrom odoo import models
odoo_import_apiImport APIfrom odoo import api
odoo_import_toolsImport toolsfrom odoo import tools
odoo_import_configImport configfrom odoo.tools import config
odoo_import_date_utilsImport date_utilsfrom odoo.tools import date_utils
odoo_import_commonImport common modulesfrom odoo import api, fields, models
odoo_import_exceptionsImport exceptionsfrom odoo.exceptions import UserError, ValidationError, AccessError, MissingError

Exceptions ​

PrefixDescriptionInserts
odoo_user_errorRaise UserErrorraise UserError(_('Error message'))
odoo_validation_errorRaise ValidationErrorraise ValidationError(_('Validation error message'))
odoo_access_errorRaise AccessErrorraise AccessError(_('Access error message'))
odoo_missing_errorRaise MissingErrorraise MissingError(_('Record not found'))
odoo_redirect_warningRaise RedirectWarningraise RedirectWarning(_('Warning message'), action_id, _('Button text'))

Models and inheritance ​

PrefixDescription
odoo_classCreate a new Odoo model class (models.Model)
odoo_transient_classCreate a TransientModel class, for wizards
odoo_abstract_classCreate an AbstractModel class, for shared behavior
odoo_extension_inheritanceCreate an extension inheritance (_name and _inherit)
odoo_classical_inheritanceCreate a classical inheritance (_inherit only)
odoo_delegation_inheritanceCreate a delegation inheritance (_inherits)
python
# odoo_class
class ModelName(models.Model):
    _name = 'model.name'
    _description = 'New Model Description'
    _order = 'id desc'  # Default ordering

    name = fields.Char()
python
# odoo_delegation_inheritance
class ModelName(models.Model):
    _name = 'model.name'
    _inherits = {'res.partner': 'partner_id'}

    partner_id = fields.Many2one('res.partner', required=True, ondelete='cascade')

odoo_transient_class and odoo_abstract_class produce the same layout as odoo_class with models.TransientModel or models.AbstractModel and a wizard or abstract description. odoo_extension_inheritance adds _inherit = 'model.to.inherit' to a class with a _name. odoo_classical_inheritance has only _inherit = 'model.name' and a new field.

Methods ​

PrefixDescription
odoo_create_methodCreate a standard create method
odoo_write_methodCreate a standard write method
odoo_unlink_methodCreate a standard unlink method
odoo_computed_fieldCreate a computed field with its compute method
odoo_onchange_methodCreate an onchange method
python
# odoo_create_method
@api.model_create_multi
def create(self, vals):
    """Create a new record with the given values."""
    return super().create(vals)
python
# odoo_computed_field
computed_field = fields.Float(string='Computed Field', compute='_compute_computed_field', store=True)

@api.depends('dependency_field')
def _compute_computed_field(self):
    """Compute the value of the field computed_field."""
    for record in self:
        record.computed_field = 0.0  # Your computation here
python
# odoo_onchange_method
@api.onchange('field_name')
def _onchange_field_name(self):
    """Triggered when the field_name changes to update related values."""
    if self.field_name:
        # Your onchange logic here
        self.another_field = self.field_name

odoo_write_method and odoo_unlink_method insert write(self, vals) and unlink(self) methods that call super().

Actions and notifications ​

PrefixDescription
odoo_return_actionReturn a window action
odoo_rainbow_man_notificationShow a rainbow man effect
odoo_warning_notificationShow a warning notification
odoo_success_notificationShow a success notification
odoo_info_notificationShow an info notification
python
# odoo_return_action
return {
    'type': 'ir.actions.act_window',
    'name': 'Window Title',
    'res_model': 'model.name',
    'view_mode': 'list,form',
    'target': 'current/new',
    'domain': [('field_name', '>', value)],
    'context': {'default_field_name': field_value},
}
python
# odoo_warning_notification (success and info use 'type': 'success' and 'type': 'info')
return {
    'type': 'ir.actions.client',
    'tag': 'display_notification',
    'params': {
        'title': _("Warning head"),
        'type': 'warning',
        'message': _("This is the detailed warning"),
        'sticky': True,
    },
}
python
# odoo_rainbow_man_notification
return {
    'effect': {
        'fadeout': 'slow',
        'message': f'Message to Display',
        'type': 'rainbow_man',
    }
}

XML snippets ​

Buttons ​

PrefixDescriptionInserts
odoo_btn_objectAdd object button<button name="button_method_name" type="object" string="Button Label" class="btn-primary"/>
odoo_btn_actionAdd action button<button name="%(action_id)d" type="action" string="Action Button" class="btn-secondary"/>
odoo_button_smartAdd smart buttonA oe_stat_button with an icon and a stat value and text
odoo_button_boxAdd button boxA oe_button_box div that contains a smart button
xml
<!-- odoo_button_box -->
<div class="oe_button_box" name="button_box">
    <button name="Button Action"
            class="oe_stat_button"
            icon="fa-bars"
            type="object"
            invisible=""
            groups="">
        <div class="o_stat_info">
            <field name="" class="o_stat_value"/>
            <span class="o_stat_text"></span>
        </div>
    </button>
</div>

Field attributes ​

PrefixDescriptionInserts
odoo_domainAdd domain to fielddomain="[('field_name', '=', value)]"
odoo_optionsAdd options to fieldoptions="{'currency_field': 'currency_id'}"
odoo_groupsAdd groups restrictiongroups="base.group_user"
odoo_field_widgetAdd widget in fieldswidget=""
odoo_field_invisibleAdd invisible conditioninvisible="state != 'done'"
odoo_field_readonlyAdd readonly conditionreadonly="not can_edit"
odoo_field_requiredAdd required conditionrequired="action == 'exist'"
odoo_field_stateAdd state field in status barA state field with the statusbar widget

View elements ​

PrefixDescriptionInserts
odoo_fieldAdd field in form or list<field name="field_name" string="Field Label" required="True"/>
odoo_labelAdd label<label for="field_name" string="Label Text"/>
odoo_separatorAdd separator<separator string="Section Title"/>
odoo_chatterAdd chatter in form<chatter/>
odoo_notebookAdd notebook blockA <notebook> with one <page>
odoo_pageAdd page element<page string="">
odoo_xpathAdd xpath block<xpath expr="//div" position="inside"> with a field
odoo_headerAdd header with button and statusbarSee below
odoo_sheetAdd sheet with group and fields<sheet> with a <group> and name and description fields
odoo_recordAdd record tag<record id="" model="">
odoo_tagAdd Odoo tagAn XML declaration with an empty <odoo> root
xml
<!-- odoo_header -->
<header>
    <button name="" string="" class="oe_highlight" invisible="" type=""/>
    <field name="state" widget="statusbar" statusbar_visible=""/>
</header>

View templates ​

PrefixDescription
odoo_form_viewCreate form view template
odoo_list_viewCreate list view template
odoo_search_viewCreate search view template
odoo_kanbanAdd kanban view template
odoo_pivot_viewCreate pivot view
odoo_calender_viewCreate calendar view

Each view template inserts a full ir.ui.view record with name, model and arch fields, named model.name.view.<type>.

xml
<!-- odoo_form_view -->
<record id="model_name_view_form" model="ir.ui.view">
    <field name="name">model.name.view.form</field>
    <field name="model">model.name</field>
    <field name="arch" type="xml">
        <form string="Form Title">
            <header>
                <!-- Buttons and statusbar go here -->
            </header>
            <sheet>
                <div class="oe_title">
                    <h1>
                        <field name="name"/>
                    </h1>
                </div>
                <group>
                    <group>
                        <field name="field1"/>
                        <field name="field2"/>
                    </group>
                    <group>
                        <field name="field3"/>
                        <field name="field4"/>
                    </group>
                </group>
            </sheet>
        </form>
    </field>
</record>
xml
<!-- odoo_list_view -->
<list string="List Title" decoration-danger="state=='cancel'" decoration-success="state=='done'">
    <field name="name"/>
    <field name="date"/>
    <field name="partner_id"/>
    <field name="amount"/>
    <field name="state"/>
</list>
xml
<!-- odoo_search_view -->
<search string="Search Title">
    <field name="name" string="Name" filter_domain="[('name','ilike',self)]"/>
    <field name="partner_id"/>
    <field name="date"/>
    <filter string="Draft" name="draft" domain="[('state','=','draft')]"/>
    <filter string="Done" name="done" domain="[('state','=','done')]"/>
    <separator/>
    <filter string="My Records" name="my_records" domain="[('user_id','=',uid)]"/>
    <group expand="0" string="Group By">
        <filter string="Partner" name="partner" context="{'group_by':'partner_id'}"/>
        <filter string="Month" name="month" context="{'group_by':'date:month'}"/>
        <filter string="Status" name="status" context="{'group_by':'state'}"/>
    </group>
</search>
xml
<!-- odoo_pivot_view -->
<pivot string="Model Name Pivot">
    <field name="name"/>
    <field name="state"/>
</pivot>
xml
<!-- odoo_kanban, as it reads in Odoo 18 -->
<kanban>
    <templates>
        <t t-name="card">
            <field name="name" class="fw-bold"/>
            <field name="description"/>
        </t>
    </templates>
</kanban>
PrefixDescriptionInserts
odoo_menu_item_rootAdd root menu item<menuitem id="module_name_menu_root" name="Module Name" sequence="10"/>
odoo_menu_item_categAdd category menu item<menuitem id="unique_id_menu_categ" name="Model Name" parent="" sequence="10"/>
odoo_menu_item_actionAdd action menu item<menuitem id="unique_id_menu_categ" name="Model Name" parent="" action="" sequence="10"/>
odoo_actionCreate action windowAn ir.actions.act_window record
odoo_inherit_viewCreate inherit viewAn ir.ui.view record with inherit_id and an xpath example
xml
<!-- odoo_action -->
<record id="model_name_action" model="ir.actions.act_window">
    <field name="name">Model Name</field>
    <field name="res_model">model.name</field>
    <field name="view_mode">list,form</field>
    <field name="context">{}</field>
    <field name="help" type="html">
        <p class="o_view_nocontent_smiling_face">
            Create your first record
        </p>
    </field>
</record>
xml
<!-- odoo_inherit_view -->
<record id="model_name_view_type_view_inherit" model="ir.ui.view">
    <field name="name">model.name.view.type.view.inherit</field>
    <field name="model">model.name</field>
    <field name="inherit_id" ref="module.original_form_view_id"/>
    <field name="arch" type="xml">
        <!-- Add fields to an existing group -->
        <xpath expr="//group[1]" position="inside">
            <field name="new_field1"/>
            <field name="new_field2"/>
        </xpath>
    </field>
</record>

Tips and limits ​

  • Snippets insert a starting point, not version-specific code. Check the result against your Odoo version. The kanban template changed in Odoo 18, and the list view type is list from Odoo 18.
  • The prefix odoo_calender_view is spelled as the plugin defines it. The calendar template needs the correct <calendar> view tag for your Odoo version, so check it after you insert it.
  • Modify snippets to fit your project, and add docstrings and comments.
  • Name fields descriptively, group related methods together, and think about access rights when you add models and views.

Next steps ​

Built by Cybrosys Technologies.