Expanding the number of fields in an Odoo many-to-many field

To add an one2many field and enable the user to select multiple lines and save them to DB, start by creating a custom one2many field on the right model, whether it is an existing one like product.template or a new one like my_model. However, when making it available in a webform, you cannot just use it as one2many field like in backend templates. Instead, you need to use html input fields. After that, create your custom controller file (e.g. /your_module/controllers/main.py), and create the “route” and the “def” corresponding to your form action (/create/weboperation) in this main.py file.


My objective is to establish a precise allocation feature in the hr.employee module, which is a subclass of


. The approach involves:

  1. Access the wizard by clicking on the Fine Allocation menu. In the wizard, you will find a field named employee_ids that has a many-to-many relationship with hr.employee. This feature allows you to choose multiple employees at once and allocate fines for them collectively.

In the field named


, fines can be assigned to each employee in the respective lines. With just a click of a button, the fines can then be allocated.

How can the fine_amount field be added to the many2many field?

Adding this field to the hr.employee form does not include it in the selected fields within the many2many lines.

My code looks like this

class FineAllocation(models.TransientModel):
_name = 'fine.allocation'
_description = 'Fine Allocation'
def action_allocate_fine(self):
employee_ids = fields.Many2many('hr.employee','hr_employee_group_rel', 'deductions_id' 'Employees')
fine_amount = fields.Float(string='Fine Amount')

This pertains to the display of records for wizards.

        Employee Fine Allocation Form
This wizard will allocate fines for all selected employee(s) equalling the input fine amount.

Solution 1:

The default view is shown by the many2many field.

Upon request by (

model, type
), the default view that corresponds to the model and type with the lowest priority will be provided.

To display the field in the many2many list, you have the option of either extending the default view or creating a new view. Consider trying either of the available methods.

  1. Extend the default tree view

  2. #msdt_code1# 

    followed by

    Define a new tree view and force the many2many field to show it:

    , and then


    followed by

    To force the many2many field to show a specific view, pass
    in context:


  3. Define the tree view in place:



When creating a tree view, specify the


setting as



Amendment 2:

With the following definition:

employee_ids = fields.Many2many('hr.employee', 'hr_employee_rel', 'payslip_id', 'Employees')

Odoo’s attempt to generate entries and assign


a value (not provided explicitly in the given instance) of


will result in the occurrence of the subsequent error.

the “employees” column of the “hr_employee_rel” relationship does not exist
LINE 2: ...   INSERT INTO hr_employee_rel (payslip_id, Employees)...



is absent in the wizard model’s employee_ids comparison.

Notice that if there is no comma between




in your question, Python will join the two strings resulting in


being assigned to


. Consequently, Odoo must generate an error message as follows:

psycopg2.errors.UndefinedColumn: ERROR: the column « deductions_idemployees » of the relation « hr_employee_group_rel » does not exist
LINE 2: ... INSERT INTO hr_employee_group_rel (deductions ...

To prevent the error, consider passing


as the string attribute. The second column (column2 attribute) is optional and will be generated automatically. You can use the following definition as a guide.

employee_ids = fields.Many2many('hr.employee', 'hr_employee_fine_allocation_rel', 'payslip_id', string='Employees')

The optional attributes, namely




, and


, can be automatically generated from model names if not provided.

If it is unnecessary to explicitly set them, the field declaration can be simplified to:

employee_ids = fields.Many2many('hr.employee', string='Employees')

Solution 2:

Ok try this, In python side:

class FineAllocation(models.TransientModel):
    _name = 'fine.allocation'
    _description = 'Fine Allocation'
    # Use one two many field because you need to information an employee and fine amount
    employee_allocation_ids = fields.One2many('fine.allocation.amount', 'Employees allocations')
    def action_allocate_fine(self):
        for rec in self.employee_allocation_ids:
            for rec in self.employee_allocation_ids:
               vals = {
                 'deduction_id': 1,
                 'computation': 'fixed',
                 'fixed': rec.fine_amount,
                 'employee_id': rec.employee_id.id,
# create the model that will hold the two information and link them to the wizard 
class FineAllocationAmount(models.TransientModel):
    _name = 'fine.allocation.amount'
    _description = 'Fine Allocation'
    fine_allocation_id = fields.Many2one('fine.allocation')
    employee_id = fields.Many2one('hr.employee', 'Employee', required=True)
    fine_amount = fields.Float('Fine amount')

In your Form view:

        Employee Fine Allocation Form
This wizard will allocate fines for all selected employee(s) equalling the input fine amount.

I hope this helps you.

Frequently Asked Questions