diff --git a/CHANGELOG b/CHANGELOG index ac743679ea..0f4c4a388f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,4 @@ +* Call getter function when accessing Function field on unsaved record * Add language configuration wizard * Allow copying attachments and notes to created records * Add link button on form diff --git a/trytond/model/fields/function.py b/trytond/model/fields/function.py index e5f2abc208..0e6e23f26d 100644 --- a/trytond/model/fields/function.py +++ b/trytond/model/fields/function.py @@ -125,6 +125,19 @@ class Function(Field): 'ir.msg_setter_function_missing', **Model.__names__(self.name))) + def __get__(self, inst, cls): + try: + return super().__get__(inst, cls) + except AttributeError: + if not self.getter.startswith('on_change_with'): + raise + value = getattr(inst, self.getter)(self.name) + # Use temporary instance to not modify instance values + temp_inst = cls() + # Set the value to have proper type + self.__set__(temp_inst, value) + return super().__get__(temp_inst, cls) + def __set__(self, inst, value): self._field.__set__(inst, value) diff --git a/trytond/tests/__init__.py b/trytond/tests/__init__.py index 0d5aac7d31..46926c8aff 100644 --- a/trytond/tests/__init__.py +++ b/trytond/tests/__init__.py @@ -19,6 +19,7 @@ def register(): from . import field_datetime from . import field_dict from . import field_float + from . import field_function from . import field_integer from . import field_many2many from . import field_many2one @@ -58,6 +59,7 @@ def register(): field_datetime.register('tests') field_dict.register('tests') field_float.register('tests') + field_function.register('tests') field_integer.register('tests') field_many2many.register('tests') field_many2one.register('tests') diff --git a/trytond/tests/field_function.py b/trytond/tests/field_function.py new file mode 100644 index 0000000000..a76e552dbb --- /dev/null +++ b/trytond/tests/field_function.py @@ -0,0 +1,32 @@ +# This file is part of Tryton. The COPYRIGHT file at the top level of +# this repository contains the full copyright notices and license terms. + +from trytond.model import ModelSQL, fields +from trytond.pool import Pool + + +class FunctionAccessor(ModelSQL): + "Function Accessor" + __name__ = 'test.function.accessor' + + target = fields.Many2One('test.function.accessor.target', "Target") + function = fields.Function( + fields.Many2One('test.function.accessor.target', "Function"), + 'on_change_with_function') + + @fields.depends('target') + def on_change_with_function(self, name=None): + if self.target: + return self.target.id + + +class FunctionAccessorTarget(ModelSQL): + "Function Accessor Target" + __name__ = 'test.function.accessor.target' + + +def register(module): + Pool.register( + FunctionAccessor, + FunctionAccessorTarget, + module=module, type_='model') diff --git a/trytond/tests/test_field_function.py b/trytond/tests/test_field_function.py new file mode 100644 index 0000000000..7c663d7d2d --- /dev/null +++ b/trytond/tests/test_field_function.py @@ -0,0 +1,32 @@ +# This file is part of Tryton. The COPYRIGHT file at the top level of +# this repository contains the full copyright notices and license terms. +import unittest + +from trytond.pool import Pool +from trytond.tests.test_tryton import activate_module, with_transaction + + +class FieldFunctionTestCase(unittest.TestCase): + "Test Field Function" + + @classmethod + def setUpClass(cls): + activate_module('tests') + + @with_transaction() + def test_accessor(self): + "Test accessing field on unsaved instance" + pool = Pool() + Model = pool.get('test.function.accessor') + Target = pool.get('test.function.accessor.target') + + target = Target() + target.save() + record = Model() + record.target = target + + self.assertEqual(record.function, target) + + +def suite(): + return unittest.TestLoader().loadTestsFromTestCase(FieldFunctionTestCase)