[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)
|
name = fields.Char('Name', required=True)
|
||||||
surname = fields.Char(compute='_compute_surname')
|
surname = fields.Char(compute='_compute_surname')
|
||||||
|
state = fields.Selection([('a', 'A'), ('b', 'B')])
|
||||||
|
|
||||||
@api.one
|
@api.one
|
||||||
@api.depends('name')
|
@api.depends('name')
|
||||||
|
@ -35,6 +36,9 @@ class mother(models.Model):
|
||||||
# extend the name field by adding a default value
|
# extend the name field by adding a default value
|
||||||
name = fields.Char(default='Unknown')
|
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
|
# override the computed field, and extend its dependencies
|
||||||
@api.one
|
@api.one
|
||||||
@api.depends('field_in_mother')
|
@api.depends('field_in_mother')
|
||||||
|
@ -44,4 +48,11 @@ class mother(models.Model):
|
||||||
else:
|
else:
|
||||||
super(mother, self)._compute_surname()
|
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:
|
# 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
|
# is accessible from the child model. This test has been written
|
||||||
# to verify the purpose of the inheritance computing of the class
|
# to verify the purpose of the inheritance computing of the class
|
||||||
# in the openerp.osv.orm._build_model.
|
# in the openerp.osv.orm._build_model.
|
||||||
mother = self.registry('test.inherit.mother')
|
mother = self.env['test.inherit.mother']
|
||||||
daugther = self.registry('test.inherit.daugther')
|
daugther = self.env['test.inherit.daugther']
|
||||||
|
|
||||||
self.assertIn('field_in_mother', mother._fields)
|
self.assertIn('field_in_mother', mother._fields)
|
||||||
self.assertIn('field_in_mother', daugther._fields)
|
self.assertIn('field_in_mother', daugther._fields)
|
||||||
|
|
||||||
def test_field_extension(self):
|
def test_field_extension(self):
|
||||||
""" check the extension of a field in an inherited model """
|
""" 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']
|
field = mother._fields['name']
|
||||||
|
|
||||||
# the field should inherit required=True, and have a default value
|
# 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):
|
def test_depends_extension(self):
|
||||||
""" check that @depends on overridden compute methods extends dependencies """
|
""" 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']
|
field = mother._fields['surname']
|
||||||
|
|
||||||
# the field dependencies are added
|
# the field dependencies are added
|
||||||
self.assertItemsEqual(field.depends, ['name', 'field_in_mother'])
|
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:
|
# 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
|
It is given as either a list of pairs (`value`, `string`), or a
|
||||||
model method, or a method name.
|
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
|
The attribute `selection` is mandatory except in the case of related
|
||||||
fields (see :ref:`field-related`) or field extensions
|
fields (see :ref:`field-related`) or field extensions
|
||||||
(see :ref:`field-incremental-definition`).
|
(see :ref:`field-incremental-definition`).
|
||||||
"""
|
"""
|
||||||
type = 'selection'
|
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):
|
def __init__(self, selection=None, string=None, **kwargs):
|
||||||
if callable(selection):
|
if callable(selection):
|
||||||
|
@ -1135,6 +1139,23 @@ class Selection(Field):
|
||||||
field = self.related_field
|
field = self.related_field
|
||||||
self.selection = lambda model: field._description_selection(model.env)
|
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):
|
def _description_selection(self, env):
|
||||||
""" return the selection list (pairs (value, label)); labels are
|
""" return the selection list (pairs (value, label)); labels are
|
||||||
translated according to context language
|
translated according to context language
|
||||||
|
|
Loading…
Reference in New Issue