Odoo Help

Welcome!

This community is for beginners and experts willing to share their Odoo knowledge. It's not a forum to discuss ideas, but a knowledge base of questions and their answers.

1

How to extend fields.selection options without overwriting them?

By
eLBati
on 6/18/13, 5:38 AM 5,640 views

Following an old discussion on openerp-expert-framework mailing list, it seems there is still no official way to extend the options of a selection field, without overwriting them.

The use case is the following:

Both module A and module B extend state field of sale.order with, respectively, stateA and stateB

Modules A and B don't know each other, so I want that if I install both of them, stateA and stateB are both added

Following the "append" method, then how to control the sequence/order of the each selection?

youring
on 6/28/14, 8:26 AM
This question has been included in the official documentation.
9

Guewen Baconnier - Software Developer, Camptocamp

--Guewen Baconnier - Software Developer, Camptocamp--
2658
| 6 7 8
Lausanne, Switzerland
--Guewen Baconnier - Software Developer, Camptocamp--

Guewen works at Camptocamp as an Odoo developer since 2010. He is the lead developer of the Odoo Connector framework and the Magento Connector. He is a delegate member of the OCA, a committer and an active contributor to the OCA projects.

 

Guewen Baconnier - Software Developer, Camptocamp
On 6/18/13, 11:28 AM

When you don't have control on the original model

Say you want to modify the selection field type of the product categories. Excerpt of the code from the product addon, that you can't modify:

class product_category(osv.osv):
    # <snip>
    _name = "product.category"
    _description = "Product Category"
    _columns = {
    # <snip>
        'type': fields.selection([('view','View'), ('normal','Normal')], 'Category Type', help="A category of the view type is a virtual category that can be used as the parent of another category to create a hierarchical structure."),
    }

In your module you need to alter the field in the _columns in the __init__ of the model:

class product_category(orm.Model):
    _inherit = 'product.category'

    def __init__(self, cr, uid, name, context=None):
        super(product_category, self).__init__(cr, uid, name, context)
        option = ('special', 'Special')
        type_selection = self._columns['type'].selection
        if option not in type_selection:
            type_selection.append(option)

When you have control on the original model

When the original model is declared in an addon that you own, you can open the selection for extension using a method:

class my_model(orm.Model):
    _name = 'my.model'

    def _type_selection(self, cr, uid, context=None):
        return [('view', 'View'), ('normal', 'Normal')]

    _columns = {
        'type': fields.selection(_type_selection, string='Type'),
    }

As a result you are now able to extend the selection in other modules as follows:

class my_model(orm.Model):
    _inherit = 'my.model'

    def _type_selection(self, cr, uid, context=None):
        selection = super(my_model, self)._type_selection(cr, uid, context=context)
        selection.append(('special', 'Special'))
        return selection

Guewen, very "essential" solution, like python wants! :) I test your code but I have an error during super call (about context), would be the super call (and so the __init__ method) parameters like this:

def __init__(self, cr, uid, name, context=None):
super(product_category, self).__init__(cr, uid, name, context=context)

TheBrush
on 6/18/13, 2:15 PM

You are right, I fixed the signature. Thanks

Camptocamp SA, Guewen Baconnier - Software Developer, Camptocamp
on 6/18/13, 2:48 PM

Updated my answer with an example when you control the declaration of the model.

Camptocamp SA, Guewen Baconnier - Software Developer, Camptocamp
on 6/18/13, 2:56 PM

Excellent explanation, thank you.

Vizucom Oy, Timo Talvitie
on 6/19/13, 9:56 AM

Two things about the second solution: _type_selection should use _() on the second member of the tuple to translate and return translated strings Also, the 'type' column won't be overwriten unless you declare it as fields.selection('_type_selection', string='Type'), (string, not function, only 8.0) or using a lambda: fields.selection(lambda self, *a, **kw: self._type_selection(*a, **kw), string='Type') The reason for this, is that declaring the function directly, binds it to the function of that class, using a string or a lambda function allow Odoo to fetch the function from self, therefore allowing overwriting

Savoir-Faire Linux, Sandy Carter
on 8/19/14, 9:52 AM

The __init__ signature seems to be something like: def __init__(self, registry, cr):

Savoir-Faire Linux, Sandy Carter
on 9/4/14, 11:46 AM
This question has been included in the official documentation.
4
TheBrush
On 6/18/13, 5:57 AM

Possibly solution: Original object (in my example: migration.server), with only one field type selection 'state':

class migration_server(osv.osv):
    _name = 'migration.server'
    _columns = {
               'state':fields.selection([
                   ('draft','Draft'),
                   ('done','Done'),                   
               ],'State', select=True, readonly=False),
    }
migration_server()

This is the new inherit class that extend the state fields.selection:

class migration_server(osv.osv):
    _name = 'migration.server'
    _inherit = 'migration.server'

    lista=[]
    def __init__(self, cr, uid, context=None):
        self.lista = self._columns['state'].selection
        if ('waiting','Waiting') not in self.lista:
            self.lista += [('waiting','Waiting')]
            self._columns['state']=fields.selection(self.lista, 'State', select=True, readonly=False),
        return
migration_server()
This question has been included in the official documentation.
2
David Béal
On 10/30/13, 8:21 AM

In case you don't have control on the original model (see Guewen response) :

As I see __init__, the method has got only these arguments : registry and cr objects

This works perfectly :

Here is another example like said by Guewen but for required attribute.

def __init__(self, pool, cr):
    super(StockPickingOut, self).__init__(pool, cr)
    self._columns['partner_id'].required = True

Please developers : do not overwrite fields definition, only change the attribute

This question has been included in the official documentation.
0
Bodi
On 6/17/16, 4:35 AM

For v6.1 (at least) Gwen's answer does not work; here is a working solution:

class res_partner_address(osv.osv):
_inherit = 'res.partner.address'
def __init__(self, pool, cr):
super(res_partner_address, self).__init__(pool, cr)
option = ('emergency', 'Emergency Contact')
type_selection = self._columns['type'].selection
if option not in type_selection:
type_selection.append(option)
res_partner_address()

Regards,

This question has been included in the official documentation.
0
Torvald Baade Bringsvor
On 10/28/15, 10:08 AM

Please be advised that this is not a problem anymore. 

PR 1612 gives you what you need.

https://github.com/odoo/odoo/pull/1612

So you can now add options as easy as 

state = fields.Selection(selection_add=[('c', 'C')])

 

Your Answer

Please try to give a substantial answer. If you wanted to comment on the question or answer, just use the commenting tool. Please remember that you can always revise your answers - no need to answer the same question twice. Also, please don't forget to vote - it really helps to select the best questions and answers!

About This Community

This community is for professionals and enthusiasts of our products and services. Read Guidelines

Question tools

1 follower(s)

Stats

Asked: 6/18/13, 5:38 AM
Seen: 5640 times
Last updated: 6/17/16, 4:35 AM