OD118 create-reads-dict¶
create() under @api.model reads its argument as one dict, but receives a list of them.
| Category | Severity | Series | Needs the index |
|---|---|---|---|
| Correctness | Error | saas~18.2 and later | no |
What it reports¶
A create method of a model class decorated with @api.model whose body reads the argument after
self as one dict: by a string key, with get, items, keys, values, setdefault, update
or pop given a string, with a string in test, or unpacked with **. The finding is at the
decorator.
A body that rebinds the argument, or tests it with isinstance, may handle a list as well, so it is
not reported, and neither is a read in a nested function or a lambda, which may name a parameter of
its own alike.
Why it matters¶
From saas~18.2, so in 19.0, @api.model on create is @api.model_create_multi: Odoo wraps a
single dict in a list before it calls the method, so the method always receives a list of dicts.
Reading it as one dict then fails on the first record created: vals["name"] raises TypeError,
vals.get("name") raises AttributeError, and "name" in vals is always false, so the code it
guards never runs. Loop over the list, and say what the method takes with @api.model_create_multi.
Before saas~18.2, Odoo calls such a method once per dict instead, which OD117 reports from saas~15.2.
Example¶
class ResPartner(models.Model):
_inherit = "res.partner"
@api.model
def create(self, vals):
vals.setdefault("comment", "Imported")
return super().create(vals)
class ResPartner(models.Model):
_inherit = "res.partner"
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
vals.setdefault("comment", "Imported")
return super().create(vals_list)