Python snippets
Type odoo and a few words in a Python file, then pick a snippet to insert ready-made Odoo code. Snippets follow the Odoo version of your project, so the code you insert uses the right syntax.
These snippets come from the bundled Odoo Helper and support Odoo 18, 19 and 20.
What you can do
- Insert a model class with the right base class and constraints for your version.
- Add a field or a method with the common arguments already filled in.
- Raise errors and show notifications with a ready-made block.
- Add the usual imports with one keyword.
- Move between placeholders with
Tab.
Get started
- Open a Python file in an Odoo module.
- Type
odooand the name of what you need, for exampleodoo new model. - Pick the snippet from the list. Use the arrow keys to move, press
EnterorTabto insert it, and pressEscto close the list. - Press
Tabto jump to each placeholder and fill it in.
Check the version in the status bar, for example Odoo v20 (Auto). Select it to change it. See Create modules and files for how the version is detected.
Models
| Snippet | What it inserts | Odoo 18 | Odoo 19 | Odoo 20 |
|---|---|---|---|---|
odoo new model class | A model with _name, _description and a name field. On Odoo 20 it also has _order, an active field and a unique-name constraint. | Yes | Yes | Yes |
odoo classical inherited model class | A new model that copies another with _name and _inherit. | Yes | Yes | Yes |
odoo delegated inherited model class | A model that embeds a parent record with _inherits and a Many2one link. | Yes | Yes | Yes |
odoo extended inherited model class | An extension of an existing model with _inherit. | Yes | Yes | Yes |
odoo abstract model | An abstract model (a mixin with no table). | Yes | Yes | Yes |
odoo transient model | A wizard model. On Odoo 20 it includes a confirm button method. | Yes | Yes | Yes |
odoo sql constraints | _sql_constraints | Yes | ||
odoo constraint | models.Constraint, which replaces _sql_constraints. | Yes | Yes | |
odoo index | A database index with models.Index. | Yes | ||
odoo unique index | A unique index, optionally partial, with an error message (models.UniqueIndex). | Yes | ||
odoo controller | An HTTP page route and a jsonrpc route. | Yes |
Fields
Type odoo and the field name, for example odoo many2one field. Each snippet has the common arguments filled in.
| Snippet | Inserts |
|---|---|
odoo boolean field | fields.Boolean(string="Name", default=False) |
odoo char field | fields.Char(string="Name", required=False, translate=False) |
odoo text field | fields.Text(string="Name", translate=False) |
odoo html field | fields.Html(string="Name", sanitize=True, translate=False) |
odoo integer field | fields.Integer(string="Name", default=0) |
odoo float field | fields.Float(string="Name", digits=(16, 2)) |
odoo monetary field | fields.Monetary(string="Name", currency_field="currency_id") |
odoo date field | fields.Date(string="Name", default=fields.Date.context_today) |
odoo datetime field | fields.Datetime(string="Name", default=fields.Datetime.now) |
odoo selection field | fields.Selection with three example choices and a default. |
odoo many2one field | fields.Many2one('res.partner', string="Name", ondelete='set null'). Choose set null, restrict or cascade from the list. |
odoo one2many field | fields.One2many('model.name', 'inverse_field_id', string="Lines") |
odoo many2many field | fields.Many2many('res.partner.category', string="Tags") |
odoo binary field | fields.Binary(string="File", attachment=True) |
odoo image field | fields.Image(string="Image", max_width=1024, max_height=1024) |
odoo reference field | fields.Reference with a list of models to choose from. |
odoo json field | fields.Json(string="Data") |
odoo many2onereference field | fields.Many2oneReference with a model_field. Odoo 20 only. |
The values above are for Odoo 20. On Odoo 18 and 19, the snippets also add a help argument and, for most fields, tracking=True.
Methods
| Snippet | What it inserts | Odoo 18 | Odoo 19 | Odoo 20 |
|---|---|---|---|---|
odoo create method | A create override that takes a list of value dictionaries (@api.model_create_multi). | Yes | Yes | Yes |
odoo write method | A write override. | Yes | Yes | Yes |
odoo unlink method | An unlink override. | Yes | Yes | Yes |
odoo onchange method | An @api.onchange method. | Yes | Yes | Yes |
odoo compute method | A computed field and its @api.depends method. | Yes | Yes | Yes |
odoo constraints method | An @api.constrains method that raises a ValidationError. | Yes | Yes | Yes |
odoo default get method | A default_get override. | Yes | Yes | Yes |
odoo action method | An action_ method that returns a window action, for example for a smart button. | Yes | Yes | Yes |
odoo ondelete method | An @api.ondelete method that blocks deletion under a condition. | Yes | ||
odoo search name method | A _search_display_name override, so name search also matches another field. | Yes | ||
odoo display name method | A _compute_display_name method that changes how records are labelled. | Yes |
Typing @api. also offers each decorator as a ready-made method, for example @api.depends with a method below it.
Errors, notifications and actions
These are the same on Odoo 18, 19 and 20.
| Snippet | What it inserts |
|---|---|
odoo validation error | raise ValidationError(...) |
odoo user error | raise UserError(...) |
odoo access error | raise AccessError(...) |
odoo missing error | raise MissingError(...) |
odoo redirect warning | raise RedirectWarning(...) with an action ID and a button label. |
odoo notification | A display_notification client action. Choose success, info, warning or danger. |
odoo rainbow man | The rainbow man effect. Choose the fade-out speed. |
odoo return action | A window action that opens a record, in the same view or in a dialog. |
odoo url action | An ir.actions.act_url action that opens a URL. |
Each error snippet needs its import, for example from odoo.exceptions import ValidationError. Use the import snippets below.
Imports
| Snippet | Inserts |
|---|---|
odoo common imports or odoo import common | from odoo import api, fields, models |
odoo import api, odoo import fields, odoo import models | The single import. |
odoo import exceptions | from odoo.exceptions import UserError, ValidationError |
odoo import http | from odoo import http |
odoo import http request | from odoo.http import request |
odoo import logging | import logging and _logger = logging.getLogger(__name__) |
odoo import tools, odoo import config, odoo import date_utils | Imports from odoo and odoo.tools. |
odoo import json, odoo import base64, odoo import re, odoo import datetime, odoo import html | Python standard library imports. |
odoo import werkzeug.utils | from werkzeug.utils import redirect |
Examples
These are Odoo 20 outputs.
# odoo new model class
from odoo import api, fields, models
class ModelName(models.Model):
_name = 'model.name'
_description = 'Model Description'
_order = 'name'
name = fields.Char(string='Name', required=True)
active = fields.Boolean(default=True)
_name_uniq = models.Constraint('unique(name)', 'The name must be unique.')# odoo compute method
field_name = fields.Char(string='Field Label', compute='_compute_field_name', store=True)
@api.depends('dependency_field')
def _compute_field_name(self):
for record in self:
record.field_name = value# odoo ondelete method
@api.ondelete(at_uninstall=False)
def _unlink_except_done(self):
for record in self:
if record.state == 'done':
raise UserError(self.env._("You cannot delete this record."))# odoo notification
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': self.env._("Title"),
'message': self.env._("Message"),
'type': 'success',
'sticky': False,
},
}# odoo controller
from odoo import http
from odoo.http import request
class MyController(http.Controller):
@http.route('/my_module/page', type='http', auth='user')
def page(self, **kwargs):
return request.render('my_module.template_id', {})
@http.route('/my_module/data', type='jsonrpc', auth='user')
def data(self, **kwargs):
return {'records': request.env['res.partner'].search_read([], ['name'], limit=10)}Tips and limits
- Snippets use the Odoo version of the project. If a snippet you expect is missing, check the version in the status bar. For example,
odoo constraintdoes not appear on Odoo 18. - Placeholders that appear more than once, such as a field name in a compute method, change together as you type.
Next steps
- Use XML snippets for views and data.
- Get context-aware suggestions as you type.
- Create modules and files.