DEV Community

Khaled Said
Khaled Said

Posted on • Edited on

Dynamic Selection List for Selection Fields in Odoo ft

Dynamic list can be approached by 3 patterns when defining selection fields in Odoo. These patterns are old however some colleagues may find them weird. These patterns are helpful instead of hard-coding the definition of each related fields.Selection.

The First Pattern:
You could define a global variable then to import in your class file definition. Such as the following global variable TYPE_TAX_USE:
addons/account/models/account_tax.py

# base class with the first definition
TYPE_TAX_USE = [
    ('sale', 'Sales'),
    ('purchase', 'Purchases'),
    ('none', 'None'),
]


class AccountTax(models.Model):
    _name = 'account.tax'

    type_tax_use = fields.Selection(TYPE_TAX_USE, string='Tax Type', required=True, default='sale')
Enter fullscreen mode Exit fullscreen mode

Now, You could import the variable as following:
addons/account/models/chart_template.py

from odoo.addons.account.models.account_tax import TYPE_TAX_USE


class AccountTaxTemplate(models.Model):
    _name = 'account.tax.template'

    type_tax_use = fields.Selection(TYPE_TAX_USE, string='Tax Type', required=True, default='sale',)
Enter fullscreen mode Exit fullscreen mode

The Second Pattern:
if the model have a relation with your model. You could use the related attribute in the field definition. internal_type field is an example in the following snippet:
addons/account/models/account_account.py

class AccountAccount(models.Model):
    _name = 'account.account'

    user_type_id = fields.Many2one('account.account.type', string='Type', required=True,)
    internal_type = fields.Selection(related='user_type_id.type', string='Internal Type' store=True, readonly=True)
Enter fullscreen mode Exit fullscreen mode

The Third Pattern:
you could use a function to return such list. This function should also be outside the class definition for auto invocation.
odoo/addons/base/models/res_partner.py

import pytz

_tzs = [(tz, tz) for tz in sorted(pytz.all_timezones, key=lambda tz: tz if not tz.startswith('Etc/') else '_')]
def _tz_get(self):
    return _tzs


class Partner(models.Model):
_name = 'res.partner'

    tz = fields.Selection(_tz_get, string='Timezone', default=lambda self: self._context.get('tz'),)
Enter fullscreen mode Exit fullscreen mode

Another example could be as following:

def _get_purchase_order_states(self):
    return self.env['purchase.order']._fields['state'].selection

class PurchaseReport(models.Model):
    _name = 'purchase.report'

    state = fields.Selection(_get_purchase_order_states, string='Order States')

Enter fullscreen mode Exit fullscreen mode

Top comments (0)