[IMP] fields: add mechanism to extend a selection field
If a selection field is defined by a list as selection, such as: state = fields.Selection([('a', 'A'), ('b', 'B')]) one can extend it by inheritance by redefining the field, as: state = fields.Selection(selection_add=[('c', 'C')]) The result is that the selection field will have the list [('a', 'A'), ('b', 'B'), ('c', 'C')] as selection.
This commit is contained in:
parent
dc9bcf479d
commit
e95fc488db
|
@ -7,6 +7,7 @@ class mother(models.Model):
|
|||
|
||||
name = fields.Char('Name', required=True)
|
||||
surname = fields.Char(compute='_compute_surname')
|
||||
state = fields.Selection([('a', 'A'), ('b', 'B')])
|
||||
|
||||
@api.one
|
||||
@api.depends('name')
|
||||
|
@ -35,6 +36,9 @@ class mother(models.Model):
|
|||
# extend the name field by adding a default value
|
||||
name = fields.Char(default='Unknown')
|
||||
|
||||
# extend the selection of the state field
|
||||
state = fields.Selection(selection_add=[('c', 'C')])
|
||||
|
||||
# override the computed field, and extend its dependencies
|
||||
@api.one
|
||||
@api.depends('field_in_mother')
|
||||
|
@ -44,4 +48,11 @@ class mother(models.Model):
|
|||
else:
|
||||
super(mother, self)._compute_surname()
|
||||
|
||||
|
||||
class mother(models.Model):
|
||||
_inherit = 'test.inherit.mother'
|
||||
|
||||
# extend again the selection of the state field
|
||||
state = fields.Selection(selection_add=[('d', 'D')])
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -9,15 +9,15 @@ class test_inherits(common.TransactionCase):
|
|||
# is accessible from the child model. This test has been written
|
||||
# to verify the purpose of the inheritance computing of the class
|
||||
# in the openerp.osv.orm._build_model.
|
||||
mother = self.registry('test.inherit.mother')
|
||||
daugther = self.registry('test.inherit.daugther')
|
||||
mother = self.env['test.inherit.mother']
|
||||
daugther = self.env['test.inherit.daugther']
|
||||
|
||||
self.assertIn('field_in_mother', mother._fields)
|
||||
self.assertIn('field_in_mother', daugther._fields)
|
||||
|
||||
def test_field_extension(self):
|
||||
""" check the extension of a field in an inherited model """
|
||||
mother = self.registry('test.inherit.mother')
|
||||
mother = self.env['test.inherit.mother']
|
||||
field = mother._fields['name']
|
||||
|
||||
# the field should inherit required=True, and have a default value
|
||||
|
@ -26,11 +26,19 @@ class test_inherits(common.TransactionCase):
|
|||
|
||||
def test_depends_extension(self):
|
||||
""" check that @depends on overridden compute methods extends dependencies """
|
||||
mother = self.registry('test.inherit.mother')
|
||||
mother = self.env['test.inherit.mother']
|
||||
field = mother._fields['surname']
|
||||
|
||||
# the field dependencies are added
|
||||
self.assertItemsEqual(field.depends, ['name', 'field_in_mother'])
|
||||
|
||||
def test_selection_extension(self):
|
||||
""" check that attribute selection_add=... extends selection on fields. """
|
||||
mother = self.env['test.inherit.mother']
|
||||
field = mother._fields['state']
|
||||
|
||||
# the extra values are added
|
||||
self.assertEqual(field.selection, [('a', 'A'), ('b', 'B'), ('c', 'C'), ('d', 'D')])
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -1116,12 +1116,16 @@ class Selection(Field):
|
|||
It is given as either a list of pairs (`value`, `string`), or a
|
||||
model method, or a method name.
|
||||
|
||||
:param selection_add: provides an extension of the selection in the case
|
||||
of an overridden field. It is a list of pairs (`value`, `string`).
|
||||
|
||||
The attribute `selection` is mandatory except in the case of related
|
||||
fields (see :ref:`field-related`) or field extensions
|
||||
(see :ref:`field-incremental-definition`).
|
||||
"""
|
||||
type = 'selection'
|
||||
selection = None # [(value, string), ...], model method or method name
|
||||
selection = None # [(value, string), ...], function or method name
|
||||
selection_add = None # [(value, string), ...]
|
||||
|
||||
def __init__(self, selection=None, string=None, **kwargs):
|
||||
if callable(selection):
|
||||
|
@ -1135,6 +1139,23 @@ class Selection(Field):
|
|||
field = self.related_field
|
||||
self.selection = lambda model: field._description_selection(model.env)
|
||||
|
||||
def _setup_regular(self, env):
|
||||
super(Selection, self)._setup_regular(env)
|
||||
# determine selection (applying extensions)
|
||||
cls = type(env[self.model_name])
|
||||
selection = None
|
||||
for field in resolve_all_mro(cls, self.name, reverse=True):
|
||||
if isinstance(field, type(self)):
|
||||
# We cannot use field.selection or field.selection_add here
|
||||
# because those attributes are overridden by `set_class_name`.
|
||||
if 'selection' in field._attrs:
|
||||
selection = field._attrs['selection']
|
||||
if 'selection_add' in field._attrs:
|
||||
selection = selection + field._attrs['selection_add']
|
||||
else:
|
||||
selection = None
|
||||
self.selection = selection
|
||||
|
||||
def _description_selection(self, env):
|
||||
""" return the selection list (pairs (value, label)); labels are
|
||||
translated according to context language
|
||||
|
|
Loading…
Reference in New Issue