Skip to content

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

models/sale_order.py
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.

models/sale_order.py
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
            )

Suppressing

total_weight = fields.Float(compute="_compute_total_weight")  # odooscan: ignore[OD204]

See suppressing a finding.