Skip to content

m2m-relation-is-label (ODW9501)

Preview (since 0.16.3.25) · Related issues · View source

Derived from the odoo linter.

This rule is unstable and in preview. The --preview flag is required for use.

What it does

Checks for a Many2many whose second positional argument reads as a label rather than as the name of a table.

Why is this bad?

Many2many takes (comodel_name, relation, column1, column2, string), so the second positional argument is the name of the relation table, not the label. Many2one takes (comodel_name, string), and a field written against that shape puts its label where the table name goes: the label is lost -- Odoo falls back to the one inferred from the field name -- and the table is created under a name nobody meant to give it, quoted capitals and spaces included.

Only a value that can not be a table name is reported: one carrying capitals or whitespace. Anything that reads like an identifier is taken at its word.

Example

class SaleCommissionPlanUserWizard(models.TransientModel):
    _name = "sale.commission.plan.user.wizard"

    user_ids = fields.Many2many("res.users", "Salespersons")

Use instead:

class SaleCommissionPlanUserWizard(models.TransientModel):
    _name = "sale.commission.plan.user.wizard"

    user_ids = fields.Many2many("res.users", string="Salespersons")

Or name the table as well, which is what Odoo would have generated:

user_ids = fields.Many2many(
    "res.users",
    "sale_commission_plan_user_wizard_res_users_rel",
    "sale_commission_plan_user_wizard_id",
    "res_users_id",
    "Salespersons",
)

No fix is offered for either shape. On a database that already ran this code the table exists under the label, so correcting the definition renames it: the rows have to be migrated from the old relation table to the new one, which is a decision for a migration script rather than for a linter.