Search Here

Set Domain of Many2One Field OnChange of Another Field

In this article you will learn how to return domain on onchange of many2one field in Odoo. In other words we are going to create a dependent drop down (many2one) field in Odoo. 

Set or Return Domain of Many2One Field OnChange of Another Field


Return Domain on Onchange of Many2One Field

For example I have two many2one fields (campus_id and department_id), and we want to change the department on the basis of campus field. To achieve this we will use @api.onchange function provided by Odoo and return domain filter.


campus_id = fields.Many2one('model.campus', string="Campus Name")
department_id = fields.Many2one('model.department', string="Department Name")

Code Description

In line no 1 we use @api.onchange decorator for campus_id. It means whenever campus changes or select a campus from many2one filed do the following line of code (3,4,5).  In line no 3 we declare a dict named res. In line no 4 we use domain to change the department field.

res['domain']      =     {'department_id':[('campus_id', '=', self.campus_id.id)]}
                                       |                                |
                                       |                                |
   (field name which is to changed)       (field name which is intended to change)

Post a Comment

18 Comments

  1. Please describe more in depth for better understanding.

    ReplyDelete
    Replies
    1. Tell me the problem you are facing?

      Delete
    2. Could you please explain how this syntax works? The post explains only 2 of the elements:
      - department_id
      - campus_id
      What exactly does 'domain' mean? 'self'? 'self.campus_id.id?

      Delete
    3. domain is the keyword provided by odoo (by using domain you can filters records), slef is the current object like "your.model(1,2,3)" here self.campus_id means from "your.model(1)" you want to get campus_id

      Delete
  2. Is it possible to create a record of another model (a mail.activity) associated to the record that has changed?

    This is my code:

    @api.onchange('stage_id')
    def _onchange_stage_id(self):
    values = self._onchange_stage_id_values(self.stage_id.id)
    event_user_id = self.user_id
    self.update(values)
    if self.stage_id.id == 3:
    self = self.env['event_mgmt.event_mgmt'].browse(self._origin.id)
    activity = self.env['mail.activity']
    activity_ins = activity.create(
    {'res_id': self.id,
    'res_model_id': 170,
    'res_model':'event_mgmt.event_mgmt',
    'activity_type_id':2,
    'summary': 'Follow Up',
    'note':'Han pasado 5 días desde el paso a propuesta. Realizar seguimiento a la propuesta enviada.',
    'date_deadline': date.today() + timedelta(days=5),
    'activity_category':'default',
    'previous_activity_type_id': False,
    'recommended_activity_type_id': False,
    'user_id': self.user_id.id
    })


    The onchange applies to a crm.lead record and I would like to create an activity (as a reminder) when the stage changes.

    Any help would be very appreciated

    ReplyDelete
    Replies
    1. under your onchange methode use below code snippet to create records for another model:

      values = {
      'key1':value1,
      'key2':value2,
      'key3':value3
      }

      create_another_model_records = self.env['another.model'].create(values)

      Delete
  3. it's not working in Odoo 12. Do we have to create on_change method in Views?

    ReplyDelete
  4. Do we have to create On_method in Views in Odoo

    ReplyDelete
  5. Hello,
    I want only administrators in the field of many2one how to can do.

    ReplyDelete
    Replies
    1. Add this group to your many2one field: groups="base.group_erp_manager"

      Delete
  6. Hi,
    Does this works the same if my onchange function is in Wizard?

    ReplyDelete
    Replies
    1. yes you can use above method in any of your model like model.Model or wizard (models.TransientModel)

      Delete
  7. boardmanagement_id = fields.Many2one('audit.boardmanagement', string='Board/Management', ondelete='set null')
    groupdivision_id = fields.Many2one('audit.groupdivision', string='Group/Division', ondelete='set null')

    @api.onchange('boardmanagement_id')
    def _boardmanagement_onchange(self):
    res = {'domain': {'groupdivision_id': [('boardmanagement_id', '=', self.boardmanagement_id.id)]}}
    return res

    Error: ValueError: Invalid field 'boardmanagement_id' in leaf "<osv.ExtendedLeaf: ('boardmanagement_id', '=', 1) on audit_groupdivision (ctx: )>"

    ReplyDelete
  8. facility_ids = fields.Many2many('hotel.facility', string="Facility")
    room_id = fields.Many2one('hotel.room', string="Room Number")

    i want to set the domain of room_id when multiple values of facility ids are selected.

    ReplyDelete
    Replies
    1. does facility_ids has room_id, if yes than you can apply domain on onchange of facility_ids. just use above code like this

      @api.multi
      @api.onchange('facility_ids')
      def set_room_domain(self):
      facility_obj = self.env['hotel.facility'].search([('some_id', '=', id_goes_here))])
      res = {}
      if facility_obj:
      room_obj = self.env['hotel.room'].sudo().search([('id', '=', facility_obj.room_id.id)])
      res['domain'] = {'room_id': [('id', 'in', room_obj.ids)]}
      return res

      Delete