Skip to content

Instantly share code, notes, and snippets.

@ryanc-me
Last active November 14, 2024 18:16
Show Gist options
  • Save ryanc-me/a0e35fb6741d73c39f9e3968eaa485ee to your computer and use it in GitHub Desktop.
Save ryanc-me/a0e35fb6741d73c39f9e3968eaa485ee to your computer and use it in GitHub Desktop.
Using res.config.settings in Odoo

Using res.config.settings in Odoo

The res.config.settings model is transient and is not saved to the database. Any fields you define on this model must be saved to the database somewhere explicitly. There are a few options.


References


Option #1

Use the related=xxx field option and a singleton model.

With this method, fields on res.config.settings will be saved to the singleton model. The values are then available on the singleton model. You can see this method in-action in the website module, where the website model stores settings from res.config.settings (link here).

  • These settings can be company-wide, or database-wide.
  • Values are saved in the my_singleton table in PostgreSQL.
from odoo import models, fields, api


class MySingleton(models.Model):
    _name = 'my.singleton'

    company_id = fields.Many2one(comodel_name='res.company')

    # define a field on our 'singleton' model
    my_setting = fields.Char()


class ResConfigSettings(models.TransientModel):
    _inherit = 'res.config.settings'

    def _default_my_singleton(self):
        # get the singleton instance. note that `company_id` is used in the search
        # domain to ensure the correct record is returned in multi-company environments
        # if the model is not multi-company-aware, you can use a blank domain
        return self.env['my.singleton'].search([('company_id', '=', self.env.company.id)], limit=1)

    # make sure a reference to the singleton is available
    my_singleton_id = fields.Many2one(comodel_name='my.singleton', default=_default_my_singleton)

    # use `related=xxx` to link back to the singleton models' field
    my_setting = fields.Char(related='my_singleton_id.my_setting')

Option #2

As an alternative to #1, the res.company model can be used instead of a singleton.

  • These settings are company-wide (i.e. they are company-aware).
  • Values are saved in the res_company table in PostgreSQL.
from odoo import models, fields, api


class ResCompany(models.Model):
    _inherit =  'res.company'

    my_setting = fields.Boolean(string='My Setting')


class ResConfigSettings(models.TransientModel):
    _inherit = 'res.config.settings'

    # company_id is already set on the res.config.settings model, and will point to
    # the currently active company
    my_setting = fields.Boolean(related='company_id.my_setting')

Option #3

Use ir.config_parameter to save configuration settings.

While this method is more terse, the ir.config_parameter model only accepts strings, so any non-string values will need to be parsed before being consumed.

  • These settings are database-wide (i.e. not company-aware).
  • Values are saved in the ir_config_parameter table in PostgreSQL.

Note: It is possible to read fields (where config_parameter is set) directly from a res.config.settings record. However, that method requires instantiating a full config settings object (which might have hundres of fields, and take seconds to load). The method outlined below is much faster.

from odoo import models, fields, api

class ResConfigSettings(models.TransientModel):
    _inherit = 'res.config.settings'

    my_char = fields.Char(config_parameter='my_module.my_string')
    my_bool = fields.Boolean(config_parameter='my_module.my_bool')
    my_float = fields.Float(config_parameter='my_module.my_float', digits=(7,4))
    my_m2o = fields.Many2one(config_parameter='my_module.my_m2o')
    my_o2m = fields.One2many(config_parameter='my_module.my_o2m')

Then, to get a copy of the setting:

def some_function(self):
    # only uid=1 has access to ir.config_parameter, so we need sudo()
    get_param = self.env['ir.config_parameter'].sudo().get_param

    # basic fields are fairly easy to parse. adding a try/except block
    # and catching ValueError() exceptions would be good practice
    my_char = get_param('my_module.my_string')
    my_bool = bool(get_param('my_module.my_bool'))
    my_float = float(get_param('my_module.my_float'))

    # x2x examples coming soon
@alisterct
Copy link

Handy! Thanks dude :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment