OD216 selection-add-without-ondelete¶
selection_add leaves a value of a required Selection with ondelete 'set null'.
| Category | Severity | Series | Needs the index |
|---|---|---|---|
| Correctness | Error | 14.0 and later | yes |
What it reports¶
A definition of a required Selection whose selection_add adds a value the field does not have
yet without giving it an ondelete policy, or that adds one and gives any value the policy
'set null'. The values the field has come from the definitions in the dependencies, in the class
that introduces the model, and earlier in the same file: those of the last selection list, which
replaces the values before it, and of the selection_add of that definition and those after it. A
selection list in the same definition replaces them too, before its selection_add applies. A
field with a single definition in scope is not checked: from 15.0 Odoo ignores the selection_add
of a lone definition. A module that Odoo always installs with base, such as web, counts as in
depends. Modules of earlier series are not checked.
Why it matters¶
When a module that adds values to a selection is uninstalled, Odoo applies each value's ondelete
policy to the records that hold it, and a value without one gets 'set null'. A required field
cannot be emptied, so Odoo refuses the definition when it sets up the model. The error stops the
registry from loading: the module cannot be installed, and a database that has it does not start.
Give each added value 'cascade', 'set default' when the field has a default, or a function that
receives the records holding the value.
A selection_add that only reorders values the field has is not reported, even when it gives one of
them 'set null': Odoo only checks a definition that adds a value. The field is not reported when
its values are computed, or are a tuple before saas~18.1, which Odoo refuses next to selection_add;
when a definition that sets them may come before or after this one, or before or after the last
selection list, so that it is unknown which list applies last or what follows it; when required
is not a literal or is unknown; or when a definition unpacks **kwargs. An attribute takes its
value from the last definitions that set it, and is unknown when those disagree, as two definitions
in different files of one module may: files load in the order of the imports, which is not indexed.
The rule does not run for a module 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.
Example¶
class ParcelRoute(models.Model):
_name = "parcel.route"
_description = "Parcel route"
state = fields.Selection([("draft", "Draft"), ("done", "Done")], required=True, default="draft")
class ParcelRouteExpress(models.Model):
_inherit = "parcel.route"
state = fields.Selection(selection_add=[("express", "Express")])
state is required, so the value express needs a policy other than 'set null'.
class ParcelRouteExpress(models.Model):
_inherit = "parcel.route"
state = fields.Selection(
selection_add=[("express", "Express")],
ondelete={"express": "set default"},
)