OD228 delegate-without-ondelete¶
A delegate=True Many2one has no ondelete, so Odoo fails when it sets up the registry.
| Category | Severity | Series | Needs the index |
|---|---|---|---|
| Correctness | Error | saas~14.4 and later, before saas~18.3 | yes |
What it reports¶
A Many2one with delegate=True that no _inherits entry names and whose ondelete is unset,
None, False or zero, reported once per module, at its last definition that sets delegate,
required or ondelete. The message names what the field lacks, required=True included.
Why it matters¶
From saas~14.4 until saas~18.2, so in 15.0 to 18.0, _inherits_check calls .lower() on the
ondelete of a delegate=True field before the field's setup gives it a default. With no value
there, Odoo fails with AttributeError, so the registry does not load and the database does not
start.
OD218 reports what Odoo only warns about or replaces. ondelete="" has a .lower(), so
Odoo replaces it with cascade and OD218 reports it. So does a field that an _inherits entry
names: Odoo guards the read of an entry's ondelete, and forces the field required with cascade.
Before saas~14.4, an unset ondelete has its default by then, as an explicit None, False or
zero does from saas~12.2. Up to saas~12.1 such an explicit value fails the same way, and OD218
reports it. From saas~18.3, so in 19.0, Odoo refuses every delegate=True field that no entry
names, whatever its attributes, which neither rule reports.
The field takes each attribute from the last definitions that set it, in this module or in its
dependencies, so an ondelete given in another class counts. An attribute is unknown when it is not
a literal, a definition unpacks **kwargs, or the last definitions that set it disagree, as two in
different files of one module may. A field with an unknown ondelete or delegate is never
reported. Neither is a related field, nor a field of a model whose _inherits may name it:
OD218 lists when that is unknown.
The rule does not run for a module of unknown series, or when the module or one of its dependencies
depends on a module that is not indexed. A model is skipped when the class that introduces it, with
_name or as a class Odoo names, is in a module outside the dependencies, or when a class of it, or
of a model it inherits or delegates to, has a plain Python base class or an _inherit element that
is not a literal, a parent whose fields the scan cannot see. A module that Odoo always installs with
base, such as web, counts as in depends.
Example¶
class ParcelLabel(models.Model):
_name = "parcel.label"
_description = "Parcel label"
partner_id = fields.Many2one("res.partner", delegate=True, required=True)
class ParcelLabel(models.Model):
_name = "parcel.label"
_description = "Parcel label"
partner_id = fields.Many2one("res.partner", delegate=True, required=True, ondelete="cascade")