OD214 many2many-table-clash¶
Two Many2many fields of a model to one comodel get the same table.
| Category | Severity | Series | Needs the index |
|---|---|---|---|
| Correctness | Error | 13.0 and later | yes |
What it reports¶
Two stored Many2many fields of one model to the same comodel that both leave out relation, and
name the same columns or none. The later field is reported, when the module adds it: the second in
the module, or the module's own when the other comes from a dependency. 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¶
Without relation, Odoo names the table after the two models' tables, and the columns after them
too, so both fields would store their links in one table and each would show the other's. Odoo
refuses two such fields when it sets up the model, and the error stops the registry from loading:
the module cannot be installed, and a database that has it does not start. Give one of them its own
relation, and column1 and column2 with it.
A field that is related or computed without store=True has no table and is not checked, nor is a
field where a definition unpacks **kwargs, a comodel or column that is not a string literal, or a
field that ends as another type. A Many2many to its own model is not reported either: Odoo refuses
it without a relation whatever the other fields are. 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 ProjectTask(models.Model):
_inherit = "project.task"
reviewer_ids = fields.Many2many("res.users")
approver_ids = fields.Many2many("res.users")
Both fields get the table project_task_res_users_rel.
class ProjectTask(models.Model):
_inherit = "project.task"
reviewer_ids = fields.Many2many("res.users", "project_task_reviewer_rel", "task_id", "user_id")
approver_ids = fields.Many2many("res.users", "project_task_approver_rel", "task_id", "user_id")