OD204 missing-method¶
A field's compute, inverse, search, selection or group_expand names a method the model
does not have.
| Category | Severity | Series | Needs the index |
|---|---|---|---|
| Correctness | Error | all | yes |
What it reports¶
A field whose compute, inverse, search, selection or group_expand is a string naming a
method that no class of the model defines, in this module or in its dependencies. A module that Odoo
always installs with base, such as web, counts as in depends. Methods inherited through
_inherit count, and so do _compute_display_name, _search_display_name and
_read_group_expand_full, which every model has. Methods of a model reached through _inherits or
delegate=True do not, since Odoo gives the model that parent's fields, not its methods.
OD312 says what defines a method.
Why it matters¶
Odoo looks the method up by name only when it needs it, so the registry loads and the error waits:
a stored computed field is computed for the existing records while the module installs, and the
install fails with AttributeError. A field that is not stored fails on its first read, from a
view or from code; an inverse fails on the first write and a search on the first search on the
field. A selection method fails when a view or an export first asks for the field's values, and a
group_expand one when a kanban or list view first groups by the field.
A related field is left alone, because Odoo replaces its compute and inverse with its own. So is a
model when a class of it, or of a model it inherits, has a plain Python base class or an _inherit
element that is not a literal, a parent whose methods the scan cannot see. Such a class of a model
reached through _inherits or delegate=True does not count, since those methods stay on that
model. A method passed as a function rather than a name is not checked: Python already refuses a
name that does not exist when it imports the file. A method that only a module missing from
depends defines counts as missing, since that module may not be installed.
The rule stays silent on a model that a dependency that is not indexed, such as an Enterprise
module, could add the method to. It still reports a model the module defines whole, with every
class and parent in the module, since that dependency loads first and cannot extend it. A model
that delegates to a model outside the module stays silent too. Add the checkout of the dependency
that is not indexed to --addons-path to check the other models.
Example¶
class SaleOrder(models.Model):
_inherit = "sale.order"
total_weight = fields.Float(compute="_compute_total_weight")
@api.depends("order_line.product_id.weight", "order_line.product_uom_qty")
def _compute_weight(self):
for order in self:
order.total_weight = sum(
line.product_id.weight * line.product_uom_qty for line in order.order_line
)
The field names _compute_total_weight, but the method is called _compute_weight.
class SaleOrder(models.Model):
_inherit = "sale.order"
total_weight = fields.Float(compute="_compute_total_weight")
@api.depends("order_line.product_id.weight", "order_line.product_uom_qty")
def _compute_total_weight(self):
for order in self:
order.total_weight = sum(
line.product_id.weight * line.product_uom_qty for line in order.order_line
)