1

i have declared two selection fields

 x = fields.Selection([('x A','x A'),('x B','x B')],string='X')
 y = fields.Selection([('0','0')],string='Y')

then i tried to add selection options to y field on onchange

 @api.onchange('x')
    def onchange_x(self):
        self.y = fields.Selection(selection_add = [('y A', 'y A'),('y B', 'y B')])

When i select from x selection i get this error

Traceback (most recent call last): File "/opt/odoo/odoo/addons/base/models/ir_http.py", line 237, in _dispatch result = request.dispatch() File "/opt/odoo/odoo/http.py", line 687, in dispatch result = self._call_function(**self.params) File "/opt/odoo/odoo/http.py", line 359, in _call_function return checked_call(self.db, *args, **kwargs) File "/opt/odoo/odoo/service/model.py", line 94, in wrapper return f(dbname, *args, **kwargs) File "/opt/odoo/odoo/http.py", line 348, in checked_call result = self.endpoint(*a, **kw) File "/opt/odoo/odoo/http.py", line 916, in call return self.method(*args, **kw) File "/opt/odoo/odoo/http.py", line 535, in response_wrap response = f(*args, **kw) File "/opt/odoo/addons/web/controllers/main.py", line 1346, in call_button action = self._call_kw(model, method, args, kwargs) File "/opt/odoo/addons/web/controllers/main.py", line 1334, in _call_kw return call_kw(request.env[model], method, args, kwargs) File "/opt/odoo/odoo/api.py", line 464, in call_kw result = _call_kw_multi(method, model, args, kwargs) File "/opt/odoo/odoo/api.py", line 451, in _call_kw_multi result = method(recs, *args, **kwargs) File "/opt/odoo/custom-addons/om_x/models/employee.py", line 34, in TestFunction self.em_pole = fields.Selection(selection_add=[('Pole A', 'Pole A'), ('Pole B', 'Pole B')], string='Pole') File "/opt/odoo/odoo/fields.py", line 1217, in set records.write({self.name: write_value}) File "/opt/odoo/addons/hr/models/hr_employee.py", line 317, in write res = super(HrEmployeePrivate, self).write(vals) File "/opt/odoo/addons/mail/models/mail_thread.py", line 323, in write result = super(MailThread, self).write(values) File "/opt/odoo/addons/mail/models/mail_activity_mixin.py", line 243, in write return super(MailActivityMixin, self).write(vals) File "/opt/odoo/odoo/models.py", line 3858, in write field.write(self, value) File "/opt/odoo/odoo/fields.py", line 1015, in write cache_value = self.convert_to_cache(value, records) File "/opt/odoo/odoo/fields.py", line 2534, in convert_to_cache raise ValueError("Wrong value for %s: %r" % (self, value)) Exception

The above exception was the direct cause of the following exception:

Traceback (most recent call last): File "/opt/odoo/odoo/http.py", line 643, in _handle_exception return super(JsonRequest, self)._handle_exception(exception) File "/opt/odoo/odoo/http.py", line 301, in _handle_exception raise exception.with_traceback(None) from new_cause ValueError: Wrong value for hr.employee.y: <odoo.fields.Selection>

can you help me please .

Zoro
  • 47
  • 5

1 Answers1

0

You should never change selection array in run-time. Selection array for Selection fields should always be static. This because odoo in background runs some migrations after installing the module, creating a support postgresql table where selection options are stored.

You can increase (using selection_add) it's options if a different module or models needs them, but still not in run-time. To achieve this, you need first to inherit the respective model, then re-define the field using selection_add argument.

module_1/models/my_model.py:

class MyModel(models.Model):
  _name = "my.model"
  
  my_selection = fields.Selection(
    selection=[('a', 'A')],
    string="My Selection"
  )

module_2/models/my_model.py:

class MyModel(models.Model):
  _inherit = "my.model"
  
  my_selection = fields.Selection(
    selection_add=[('b', 'B')],
    string="My Selection"
  )

For run-time update, your need is to use a Many2one field with a proper domain, which can then be patched via onchange decorator.

class MyOption(models.Model):
  _name = "my.option"
  
  name = fields.Char()
  filtered = fields.Boolean(default=False)

class MyModel(models.Model):
  _name = "my.model"

  show_filtered_options = fields.Boolean(default=False)
  option_id = fields.Many2one(
    comodel_name="my.option",
    domain="[('filtered', '=', show_filtered_options)]"
  )

  @api.onchange('show_filtered_options')
  def _onchange_show_filtered_options(self):
    self.ensure_one()

    return {'domain': {
        'option_id': [('filtered', '=', self.show_filtered_options)]
      }
    }

Finally, populate your options using a data XML file. Remember to append this in your "data" array inside your module manifest.

<odoo>
  <data>
    <record name="my_option_1" model="my.option">
      <field name="name">Option 1</field>
      <field name="filtered">0</field>
    </record>

    <record name="my_option_2" model="my.option">
      <field name="name">Option 2</field>
      <field name="filtered">1</field>
    </record>
  </data>
</odoo>

To replicate selection field behaviour in Many2one, you can add widget="selection" in your view.

<field name="option_id" widget="selection" />

icra
  • 460
  • 3
  • 14