Odoo coding standards
Assista IDE can check your Python and XML files against Odoo's coding guidelines as you edit, so you catch naming and structure issues before a review. The warnings are off by default.
This feature comes from the bundled Odoo Helper. Read the guidelines themselves in the Odoo documentation.
What you can do
- Catch naming issues in models, fields, methods, record IDs and file names.
- Keep files consistent across your team, for example the import order and the order of attributes in XML.
- See problems as you type, as warnings in the editor and in the Problems panel. Each warning shows the rule that was broken and the pattern to use.
Get started
- Open Settings.
- Search for Enable Code Standard Warnings.
- Turn it on.
The checks run on .py and .xml files when you open them, as you type and when you save. Every finding is a warning on the line that triggered it. Turn the setting off to clear all warnings.
What it checks
Python
Files and classes. These checks run on files in a models/ folder.
| Rule | Example |
|---|---|
| The file name is the snake_case form of the model class name. | class CustomerInvoice goes in customer_invoice.py, not customerInvoice.py. |
| Class names use CamelCase. | class CustomerInvoice, not class customer_invoice. |
The _name of a model is singular. | res.partner, not res.partners. |
The _name of a transient model follows <base_model>.<action>. | account.invoice.import. A name with no dot is flagged. |
Fields
| Rule | Example |
|---|---|
Many2one field names end in _id. | customer_id = fields.Many2one('res.partner') |
One2many and Many2many field names end in _ids. | invoice_line_ids = fields.One2many(...), category_ids = fields.Many2many(...) |
Methods
| Rule | Example |
|---|---|
Compute methods start with _compute_. | _compute_total_amount |
Search methods start with _search_. | _search_name |
Default methods start with _default_. | _default_company_id |
Selection methods start with _selection_. | _selection_state |
Onchange methods start with _onchange_. | _onchange_customer_id |
Constraint methods start with _check_. | _check_total_amount |
Action methods start with action_. | action_validate |
action_ methods call self.ensure_one() near the start. | def action_validate(self): self.ensure_one() |
A method is flagged when its name contains one of the keywords (compute, search, default, selection, onchange, check or action) but does not start with the matching prefix. compute_total_amount is flagged, and so is a core override such as default_get. You can ignore the warning on those overrides.
Imports. Order imports in three groups: the Python standard library, then odoo, then odoo.addons.
import datetime
import logging
from odoo import api, fields, models
from odoo.addons.base.models import ir_modelPatterns to avoid
| Pattern | Use instead |
|---|---|
.clone() | dict(my_dict) or list(my_list) |
cr.commit() | Let Odoo commit. Commit yourself only on a cursor you created. |
_('Welcome %s' % name), formatting before translation | _('Welcome %s', name) |
_('Welcome ' + name), concatenation inside _() | One complete string literal. |
_('Welcome') % name, formatting after translation | Put the values inside the _() call. |
_('Name: %s' % _(name)), a nested _() | Leave field values untranslated. Odoo translates them. |
if len(records) > 0: | if records: |
for key in my_dict.keys(): | for key in my_dict: |
my_dict.get('key', None) | my_dict.get('key') |
INFO
The translation check flags any % inside _(), including the recommended _('Welcome %s', name). If you follow the recommended form, you can ignore that warning.
XML
Elements and attributes
| Rule | Example |
|---|---|
On a <record>, put id before model. | <record id="customer_invoice_view_form" model="ir.ui.view"> |
On a <field>, put name first. | <field name="invoice_number" type="char"> |
Put noupdate="1" on <odoo>, not on <data>. | <odoo noupdate="1"> |
Use <menuitem>, not a record of ir.ui.menu. | <menuitem id="customer_invoice_menu" .../> |
IDs. A check applies to an ID when it contains the marker shown.
| Record | Pattern | Example |
|---|---|---|
Menu, ID contains _menu | <model>_menu or <model>_menu_<detail> | customer_invoice_menu_main |
View, any ID inside an ir.ui.view record | <model>_view_<type>, optionally ending in _inherit. The type is form, list, kanban, search, calendar, graph, pivot, activity or tree. | customer_invoice_view_form |
Action, ID contains _action | <model>_action or <model>_action_<detail> | customer_invoice_action |
Group, ID contains _group_ | <module>_group_<name> | invoice_group_manager |
Rule, ID contains _rule_ | <model>_rule_<group> | customer_invoice_rule_company |
View names. In an ir.ui.view record, the name field uses dots and the form <model.name>.view.<type>, such as customer.invoice.view.form. For an inherited view, the name ends with .inherit.<details>, such as customer.invoice.view.form.inherit.partner.
File names
The check uses the name of the folder that holds the file.
| Folder | Files must be named |
|---|---|
views/ (XML) | *_views.xml, *_templates.xml or *_menus.xml |
security/ (XML) | *_groups.xml or *_security.xml |
report/ (XML) | *_report_views.xml, *_reports.xml or *_templates.xml |
wizard/ (XML) | *_views.xml |
data/ (XML) | *_data.xml or *_demo.xml |
controllers/ (Python) | snake_case, such as main.py or portal.py |
wizard/ (Python) | snake_case |
report/ (Python) | *_report.py |
Access files (ir.model.access.csv and, on Odoo 20, ir.access.csv) are CSV files and are not checked.
Tips and limits
- Warnings are suggestions based on Odoo's guidelines. You decide what to change.
- The checks only read
.pyand.xmlfiles. They do not check CSV files. - Turn the setting off again at any time if the warnings are noisy for an older project.
- Files that the file and module generators create can still trigger a few warnings, such as a placeholder view ID. Rename them as you fill in the template.
Next steps
- Get context-aware suggestions.
- Review a module with a full QA check.