Call getter function when accessing Function field
If the record is unsaved and the getter is based on on_change_with, we can call the getter to compute the value. This value must not be stored in the cache as it may change prior to saving. issue4193 issue9263 review317291002
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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')
|
||||
@@ -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)
|
||||
Reference in New Issue
Block a user