Set context on record instantiated in Field.__set__ and read related
Field may have a context defined so when it instantiate a relational record, the field should set this context like when the record is read from the database in ModelStorage.__getattr__. And when such field is read as related field, the context should also be set. issue8225 review287171002
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
* Set context on record instantiated by Field.__set__
|
||||
* Set context when reading related fields
|
||||
* Check read access on field in search order (issue8189)
|
||||
* Add base64 converter to URL map
|
||||
* Add HTML widget
|
||||
|
||||
@@ -9,7 +9,7 @@ from sql.conditionals import Coalesce, NullIf
|
||||
from sql.operators import Concat
|
||||
|
||||
from trytond import backend
|
||||
from trytond.pyson import PYSON, PYSONEncoder, Eval
|
||||
from trytond.pyson import PYSON, PYSONEncoder, PYSONDecoder, Eval
|
||||
from trytond.const import OPERATORS
|
||||
from trytond.tools.string_ import StringPartitioned
|
||||
from trytond.transaction import Transaction
|
||||
@@ -162,6 +162,21 @@ def instanciate_values(Target, value):
|
||||
return tuple(instance(x) for x in (value or []))
|
||||
|
||||
|
||||
def instantiate_context(field, record):
|
||||
from ..modelstorage import EvalEnvironment
|
||||
ctx = {}
|
||||
if field.context:
|
||||
pyson_context = PYSONEncoder().encode(field.context)
|
||||
ctx.update(PYSONDecoder(
|
||||
EvalEnvironment(record, record.__class__)).decode(
|
||||
pyson_context))
|
||||
datetime_ = None
|
||||
if getattr(field, 'datetime_field', None):
|
||||
datetime_ = getattr(record, field.datetime_field, None)
|
||||
ctx = {'_datetime': datetime_}
|
||||
return ctx
|
||||
|
||||
|
||||
def on_change_result(record):
|
||||
return record._changed_values
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from sql.conditionals import Coalesce
|
||||
|
||||
from trytond.pyson import PYSONEncoder
|
||||
from .field import (Field, size_validate, instanciate_values, domain_validate,
|
||||
search_order_validate, context_validate)
|
||||
search_order_validate, context_validate, instantiate_context)
|
||||
from ...pool import Pool
|
||||
from ...tools import grouped_slice
|
||||
from ...transaction import Transaction
|
||||
@@ -278,7 +278,10 @@ class Many2Many(Field):
|
||||
|
||||
def __set__(self, inst, value):
|
||||
Target = self.get_target()
|
||||
super(Many2Many, self).__set__(inst, instanciate_values(Target, value))
|
||||
ctx = instantiate_context(self, inst)
|
||||
with Transaction().set_context(ctx):
|
||||
records = instanciate_values(Target, value)
|
||||
super(Many2Many, self).__set__(inst, records)
|
||||
|
||||
def convert_domain_tree(self, domain, tables):
|
||||
Target = self.get_target()
|
||||
|
||||
@@ -7,7 +7,7 @@ from sql.operators import Or
|
||||
|
||||
from trytond.pyson import PYSONEncoder
|
||||
from .field import (Field, search_order_validate, context_validate,
|
||||
with_inactive_records)
|
||||
with_inactive_records, instantiate_context)
|
||||
from ...pool import Pool
|
||||
from ...tools import reduce_ids
|
||||
from ...transaction import Transaction
|
||||
@@ -100,10 +100,13 @@ class Many2One(Field):
|
||||
|
||||
def __set__(self, inst, value):
|
||||
Target = self.get_target()
|
||||
if isinstance(value, dict):
|
||||
value = Target(**value)
|
||||
elif isinstance(value, int):
|
||||
value = Target(value)
|
||||
if isinstance(value, (dict, int)):
|
||||
ctx = instantiate_context(self, inst)
|
||||
with Transaction().set_context(ctx):
|
||||
if isinstance(value, dict):
|
||||
value = Target(**value)
|
||||
elif isinstance(value, int):
|
||||
value = Target(value)
|
||||
assert isinstance(value, (Target, type(None)))
|
||||
super(Many2One, self).__set__(inst, value)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ from sql.conditionals import Coalesce
|
||||
|
||||
from trytond.pyson import PYSONEncoder
|
||||
from .field import (Field, size_validate, instanciate_values, domain_validate,
|
||||
search_order_validate, context_validate)
|
||||
search_order_validate, context_validate, instantiate_context)
|
||||
from ...pool import Pool
|
||||
from ...tools import grouped_slice
|
||||
from ...transaction import Transaction
|
||||
@@ -253,7 +253,10 @@ class One2Many(Field):
|
||||
|
||||
def __set__(self, inst, value):
|
||||
Target = self.get_target()
|
||||
super(One2Many, self).__set__(inst, instanciate_values(Target, value))
|
||||
ctx = instantiate_context(self, inst)
|
||||
with Transaction().set_context(ctx):
|
||||
records = instanciate_values(Target, value)
|
||||
super(One2Many, self).__set__(inst, records)
|
||||
|
||||
def convert_domain(self, domain, tables, Model):
|
||||
from ..modelsql import convert_from
|
||||
|
||||
@@ -7,7 +7,7 @@ from sql.functions import Substring, Position
|
||||
|
||||
from trytond.pyson import PYSONEncoder
|
||||
from .field import (Field, search_order_validate, context_validate,
|
||||
with_inactive_records)
|
||||
with_inactive_records, instantiate_context)
|
||||
from .selection import SelectionMixin
|
||||
from ...transaction import Transaction
|
||||
from ...pool import Pool
|
||||
@@ -144,10 +144,12 @@ class Reference(SelectionMixin, Field):
|
||||
else:
|
||||
target, value = value
|
||||
Target = Pool().get(target)
|
||||
if isinstance(value, dict):
|
||||
value = Target(**value)
|
||||
else:
|
||||
value = Target(value)
|
||||
ctx = instantiate_context(self, inst)
|
||||
with Transaction().set_context(ctx):
|
||||
if isinstance(value, dict):
|
||||
value = Target(**value)
|
||||
else:
|
||||
value = Target(value)
|
||||
super(Reference, self).__set__(inst, value)
|
||||
|
||||
def sql_format(self, value):
|
||||
|
||||
+35
-37
@@ -1,7 +1,7 @@
|
||||
# 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 datetime
|
||||
from itertools import islice, chain, product
|
||||
from itertools import islice, chain, product, groupby
|
||||
from collections import OrderedDict, defaultdict
|
||||
from functools import wraps
|
||||
|
||||
@@ -19,6 +19,7 @@ from trytond import backend
|
||||
from trytond.tools import reduce_ids, grouped_slice, cursor_dict
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import PYSONEncoder, PYSONDecoder
|
||||
from trytond.cache import LRUDict
|
||||
from trytond.exceptions import ConcurrencyException
|
||||
from trytond.rpc import RPC
|
||||
@@ -690,19 +691,21 @@ class ModelSQL(ModelStorage):
|
||||
# construct a clause for the rules :
|
||||
domain = Rule.domain_get(cls.__name__, mode='read')
|
||||
|
||||
fields_related = {}
|
||||
datetime_fields = []
|
||||
fields_related = defaultdict(set)
|
||||
extra_fields = set()
|
||||
for field_name in fields_names:
|
||||
if field_name == '_timestamp':
|
||||
continue
|
||||
if '.' in field_name:
|
||||
field, field_related = field_name.split('.', 1)
|
||||
fields_related.setdefault(field, [])
|
||||
fields_related[field].append(field_related)
|
||||
else:
|
||||
field = cls._fields[field_name]
|
||||
field_name, field_related = field_name.split('.', 1)
|
||||
fields_related[field_name].add(field_related)
|
||||
field = cls._fields[field_name]
|
||||
if hasattr(field, 'datetime_field') and field.datetime_field:
|
||||
datetime_fields.append(field.datetime_field)
|
||||
extra_fields.add(field.datetime_field)
|
||||
if field.context:
|
||||
extra_fields.update(fields.get_eval_fields(field.context))
|
||||
all_fields = (
|
||||
set(fields_names) | set(fields_related.keys()) | extra_fields)
|
||||
|
||||
result = []
|
||||
table = cls.__table__()
|
||||
@@ -722,7 +725,7 @@ class ModelSQL(ModelStorage):
|
||||
history_limit = 1
|
||||
|
||||
columns = []
|
||||
for f in fields_names + list(fields_related.keys()) + datetime_fields:
|
||||
for f in all_fields:
|
||||
field = cls._fields.get(f)
|
||||
if field and field.sql_type():
|
||||
columns.append(field.sql_column(table).as_(f))
|
||||
@@ -779,8 +782,7 @@ class ModelSQL(ModelStorage):
|
||||
cachable_fields.append(fname)
|
||||
|
||||
# all fields for which there is a get attribute
|
||||
getter_fields = [f for f in
|
||||
fields_names + list(fields_related.keys()) + datetime_fields
|
||||
getter_fields = [f for f in all_fields
|
||||
if f in cls._fields and hasattr(cls._fields[f], 'get')]
|
||||
|
||||
if getter_fields and cachable_fields:
|
||||
@@ -833,15 +835,6 @@ class ModelSQL(ModelStorage):
|
||||
for row in result:
|
||||
row[fname] = getter_result[row['id']]
|
||||
|
||||
def group_by(rows, keyfunc=None):
|
||||
result = defaultdict(list)
|
||||
if keyfunc is None:
|
||||
result[None] = rows
|
||||
else:
|
||||
for row in rows:
|
||||
result[keyfunc(row)].append(row)
|
||||
return result
|
||||
|
||||
def read_related(field, Target, rows, fields):
|
||||
name = field.name
|
||||
target_ids = []
|
||||
@@ -880,7 +873,7 @@ class ModelSQL(ModelStorage):
|
||||
row[key] = None
|
||||
|
||||
to_del = set()
|
||||
for fname in chain(fields_related.keys(), datetime_fields):
|
||||
for fname in set(fields_related.keys()) | extra_fields:
|
||||
if fname not in fields_names:
|
||||
to_del.add(fname)
|
||||
if fname not in cls._fields:
|
||||
@@ -889,27 +882,32 @@ class ModelSQL(ModelStorage):
|
||||
continue
|
||||
field = cls._fields[fname]
|
||||
datetime_field = getattr(field, 'datetime_field', None)
|
||||
if field._type == 'reference':
|
||||
def keyfunc(row):
|
||||
|
||||
def keyfunc(row):
|
||||
ctx = {}
|
||||
if field.context:
|
||||
pyson_context = PYSONEncoder().encode(field.context)
|
||||
ctx.update(PYSONDecoder(row).decode(pyson_context))
|
||||
if datetime_field:
|
||||
ctx['_datetime'] = row.get(datetime_field)
|
||||
if field._type == 'reference':
|
||||
value = row[fname]
|
||||
if not value:
|
||||
return (None, None)
|
||||
model, _ = value.split(',', 1)
|
||||
return (pool.get(model), row.get(datetime_field))
|
||||
else:
|
||||
Target = field.get_target()
|
||||
Target = None
|
||||
else:
|
||||
model, _ = value.split(',', 1)
|
||||
Target = pool.get(model)
|
||||
else:
|
||||
Target = field.get_target()
|
||||
return Target, ctx
|
||||
|
||||
def keyfunc(row):
|
||||
return (Target, row.get(datetime_field))
|
||||
for (Target, datetime_), rows in group_by(
|
||||
result, keyfunc).items():
|
||||
ctx = {}
|
||||
if datetime_:
|
||||
ctx['_datetime'] = datetime_
|
||||
for (Target, ctx), rows in groupby(
|
||||
sorted(result, key=keyfunc), key=keyfunc):
|
||||
rows = list(rows)
|
||||
with Transaction().set_context(ctx):
|
||||
if Target:
|
||||
targets = read_related(
|
||||
field, Target, rows, fields_related[fname])
|
||||
field, Target, rows, list(fields_related[fname]))
|
||||
targets = {t['id']: t for t in targets}
|
||||
else:
|
||||
targets = {}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
from trytond.model import ModelSQL, fields
|
||||
from trytond.pool import Pool
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
class Many2Many(ModelSQL):
|
||||
@@ -154,6 +155,31 @@ class Many2ManyTreeRelation(ModelSQL):
|
||||
child = fields.Many2One('test.many2many_tree', 'Child')
|
||||
|
||||
|
||||
class Many2ManyContext(ModelSQL):
|
||||
"Many2Many Context"
|
||||
__name__ = 'test.many2many_context'
|
||||
targets = fields.Many2Many(
|
||||
'test.many2many_context.relation', 'origin', 'target', "Targets",
|
||||
context={'test': 'foo'})
|
||||
|
||||
|
||||
class Many2ManyContextRelation(ModelSQL):
|
||||
"Many2Many Context Relation"
|
||||
__name__ = 'test.many2many_context.relation'
|
||||
origin = fields.Many2One('test.many2many_context', "Origin")
|
||||
target = fields.Many2One('test.many2many_context.target', "Target")
|
||||
|
||||
|
||||
class Many2ManyContextTarget(ModelSQL):
|
||||
"Many2Many Context Target"
|
||||
__name__ = 'test.many2many_context.target'
|
||||
context = fields.Function(fields.Char("context"), 'get_context')
|
||||
|
||||
def get_context(self, name):
|
||||
context = Transaction().context
|
||||
return context.get('test')
|
||||
|
||||
|
||||
def register(module):
|
||||
Pool.register(
|
||||
Many2Many,
|
||||
@@ -176,4 +202,7 @@ def register(module):
|
||||
Many2ManyFilterDomainRelation,
|
||||
Many2ManyTree,
|
||||
Many2ManyTreeRelation,
|
||||
Many2ManyContext,
|
||||
Many2ManyContextTarget,
|
||||
Many2ManyContextRelation,
|
||||
module=module, type_='model')
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
from trytond.model import ModelSQL, ModelStorage, DeactivableMixin, fields
|
||||
from trytond.pool import Pool
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
class Many2OneTarget(DeactivableMixin, ModelSQL):
|
||||
@@ -64,6 +65,24 @@ class Many2OneMPTT(ModelSQL):
|
||||
return 0
|
||||
|
||||
|
||||
class Many2OneContext(ModelSQL):
|
||||
"Many2One Context"
|
||||
__name__ = 'test.many2one_context'
|
||||
target = fields.Many2One(
|
||||
'test.many2one_context.target', "target",
|
||||
context={'test': 'foo'})
|
||||
|
||||
|
||||
class Many2OneTargetContext(ModelSQL):
|
||||
"Many2One Target Context"
|
||||
__name__ = 'test.many2one_context.target'
|
||||
context = fields.Function(fields.Char("context"), 'get_context')
|
||||
|
||||
def get_context(self, name):
|
||||
context = Transaction().context
|
||||
return context.get('test')
|
||||
|
||||
|
||||
def register(module):
|
||||
Pool.register(
|
||||
Many2OneTarget,
|
||||
@@ -73,4 +92,6 @@ def register(module):
|
||||
Many2OneTargetStorage,
|
||||
Many2OneTree,
|
||||
Many2OneMPTT,
|
||||
Many2OneContext,
|
||||
Many2OneTargetContext,
|
||||
module=module, type_='model')
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
from trytond.model import ModelSQL, fields
|
||||
from trytond.pool import Pool
|
||||
from trytond.pyson import Eval
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
class One2Many(ModelSQL):
|
||||
@@ -110,6 +111,25 @@ class One2ManyFilterDomainTarget(ModelSQL):
|
||||
value = fields.Integer('Value')
|
||||
|
||||
|
||||
class One2ManyContext(ModelSQL):
|
||||
"One2Many Context"
|
||||
__name__ = 'test.one2many_context'
|
||||
targets = fields.One2Many(
|
||||
'test.one2many_context.target', 'origin', "Targets",
|
||||
context={'test': 'foo'})
|
||||
|
||||
|
||||
class One2ManyContextTarget(ModelSQL):
|
||||
"One2Many Context Target"
|
||||
__name__ = 'test.one2many_context.target'
|
||||
origin = fields.Many2One('test.one2many_context', "Origin")
|
||||
context = fields.Function(fields.Char("context"), 'get_context')
|
||||
|
||||
def get_context(self, name):
|
||||
context = Transaction().context
|
||||
return context.get('test')
|
||||
|
||||
|
||||
def register(module):
|
||||
Pool.register(
|
||||
One2Many,
|
||||
@@ -126,4 +146,6 @@ def register(module):
|
||||
One2ManyFilterTarget,
|
||||
One2ManyFilterDomain,
|
||||
One2ManyFilterDomainTarget,
|
||||
One2ManyContext,
|
||||
One2ManyContextTarget,
|
||||
module=module, type_='model')
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
from trytond.model import ModelSQL, fields
|
||||
from trytond.pool import Pool
|
||||
from trytond.transaction import Transaction
|
||||
|
||||
|
||||
class Reference(ModelSQL):
|
||||
@@ -29,9 +30,29 @@ class ReferenceRequired(ModelSQL):
|
||||
], required=True)
|
||||
|
||||
|
||||
class ReferenceContext(ModelSQL):
|
||||
"Reference Context"
|
||||
__name__ = 'test.reference_context'
|
||||
target = fields.Reference("Reference", selection=[
|
||||
('test.reference_context.target', "Target"),
|
||||
], context={'test': 'foo'})
|
||||
|
||||
|
||||
class ReferenceContextTarget(ModelSQL):
|
||||
"Reference Context Target"
|
||||
__name__ = 'test.reference_context.target'
|
||||
context = fields.Function(fields.Char("context"), 'get_context')
|
||||
|
||||
def get_context(self, name):
|
||||
context = Transaction().context
|
||||
return context.get('test')
|
||||
|
||||
|
||||
def register(module):
|
||||
Pool.register(
|
||||
Reference,
|
||||
ReferenceTarget,
|
||||
ReferenceRequired,
|
||||
ReferenceContext,
|
||||
ReferenceContextTarget,
|
||||
module=module, type_='model')
|
||||
|
||||
@@ -625,6 +625,43 @@ class FieldMany2ManyTestCase(unittest.TestCase, CommonTestCaseMixin):
|
||||
self.first1, self.first2, self.first3, self.first4,
|
||||
self.second1, self.second2, self.second3, self.second4]))
|
||||
|
||||
@with_transaction()
|
||||
def test_context_attribute(self):
|
||||
"Test context on many2many attribute"
|
||||
pool = Pool()
|
||||
Many2Many = pool.get('test.many2many_context')
|
||||
|
||||
record, = Many2Many.create([{
|
||||
'targets': [('create', [{}])],
|
||||
}])
|
||||
|
||||
self.assertEqual(record.targets[0].context, 'foo')
|
||||
|
||||
@with_transaction()
|
||||
def test_context_read(self):
|
||||
"Test context on many2many read"
|
||||
pool = Pool()
|
||||
Many2Many = pool.get('test.many2many_context')
|
||||
|
||||
record, = Many2Many.create([{
|
||||
'targets': [('create', [{}])],
|
||||
}])
|
||||
data, = Many2Many.read([record.id], ['targets.context'])
|
||||
|
||||
self.assertEqual(data['targets.'][0]['context'], 'foo')
|
||||
|
||||
@with_transaction()
|
||||
def test_context_set(self):
|
||||
"Test context on many2many set"
|
||||
pool = Pool()
|
||||
Many2Many = pool.get('test.many2many_context')
|
||||
Target = pool.get('test.many2many_context.target')
|
||||
|
||||
target, = Target.create([{}])
|
||||
record = Many2Many(targets=[target.id])
|
||||
|
||||
self.assertEqual(record.targets[0].context, 'foo')
|
||||
|
||||
|
||||
class FieldMany2ManyReferenceTestCase(unittest.TestCase, CommonTestCaseMixin):
|
||||
"Test Field Many2Many Reference"
|
||||
|
||||
@@ -467,6 +467,47 @@ class FieldMany2OneTestCase(unittest.TestCase):
|
||||
"Test search many2one mptt not parent of empty"
|
||||
self._test_search_not_parent_of_empty('test.many2one_mptt')
|
||||
|
||||
@with_transaction()
|
||||
def test_context_attribute(self):
|
||||
"Test context on many2one attribute"
|
||||
pool = Pool()
|
||||
Many2One = pool.get('test.many2one_context')
|
||||
Target = pool.get('test.many2one_context.target')
|
||||
|
||||
target, = Target.create([{}])
|
||||
record, = Many2One.create([{
|
||||
'target': target.id,
|
||||
}])
|
||||
|
||||
self.assertEqual(record.target.context, 'foo')
|
||||
|
||||
@with_transaction()
|
||||
def test_context_read(self):
|
||||
"Test context on many2one read"
|
||||
pool = Pool()
|
||||
Many2One = pool.get('test.many2one_context')
|
||||
Target = pool.get('test.many2one_context.target')
|
||||
|
||||
target, = Target.create([{}])
|
||||
record, = Many2One.create([{
|
||||
'target': target.id,
|
||||
}])
|
||||
data, = Many2One.read([record.id], ['target.context'])
|
||||
|
||||
self.assertEqual(data['target.']['context'], 'foo')
|
||||
|
||||
@with_transaction()
|
||||
def test_context_set(self):
|
||||
"Test context on many2one set"
|
||||
pool = Pool()
|
||||
Many2One = pool.get('test.many2one_context')
|
||||
Target = pool.get('test.many2one_context.target')
|
||||
|
||||
target, = Target.create([{}])
|
||||
record = Many2One(target=target.id)
|
||||
|
||||
self.assertEqual(record.target.context, 'foo')
|
||||
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(FieldMany2OneTestCase)
|
||||
|
||||
@@ -455,6 +455,43 @@ class FieldOne2ManyTestCase(unittest.TestCase, CommonTestCaseMixin):
|
||||
self.assertListEqual(one2manys, [one2many])
|
||||
self.assertListEqual(one2manys_filtered, [])
|
||||
|
||||
@with_transaction()
|
||||
def test_context_attribute(self):
|
||||
"Test context on one2many attribute"
|
||||
pool = Pool()
|
||||
Many2One = pool.get('test.one2many_context')
|
||||
|
||||
record, = Many2One.create([{
|
||||
'targets': [('create', [{}])],
|
||||
}])
|
||||
|
||||
self.assertEqual(record.targets[0].context, 'foo')
|
||||
|
||||
@with_transaction()
|
||||
def test_context_read(self):
|
||||
"Test context on one2many read"
|
||||
pool = Pool()
|
||||
Many2One = pool.get('test.one2many_context')
|
||||
|
||||
record, = Many2One.create([{
|
||||
'targets': [('create', [{}])],
|
||||
}])
|
||||
data, = Many2One.read([record.id], ['targets.context'])
|
||||
|
||||
self.assertEqual(data['targets.'][0]['context'], 'foo')
|
||||
|
||||
@with_transaction()
|
||||
def test_context_set(self):
|
||||
"Test context on one2many set"
|
||||
pool = Pool()
|
||||
Many2One = pool.get('test.one2many_context')
|
||||
Target = pool.get('test.one2many_context.target')
|
||||
|
||||
target, = Target.create([{}])
|
||||
record = Many2One(targets=[target.id])
|
||||
|
||||
self.assertEqual(record.targets[0].context, 'foo')
|
||||
|
||||
|
||||
class FieldOne2ManyReferenceTestCase(unittest.TestCase, CommonTestCaseMixin):
|
||||
"Test Field One2Many Reference"
|
||||
|
||||
@@ -398,6 +398,47 @@ class FieldReferenceTestCase(unittest.TestCase):
|
||||
|
||||
self.assertEqual(reference.reference, None)
|
||||
|
||||
@with_transaction()
|
||||
def test_context_attribute(self):
|
||||
"Test context on reference attribute"
|
||||
pool = Pool()
|
||||
Reference = pool.get('test.reference_context')
|
||||
Target = pool.get('test.reference_context.target')
|
||||
|
||||
target, = Target.create([{}])
|
||||
record, = Reference.create([{
|
||||
'target': str(target),
|
||||
}])
|
||||
|
||||
self.assertEqual(record.target.context, 'foo')
|
||||
|
||||
@with_transaction()
|
||||
def test_context_read(self):
|
||||
"Test context on reference read"
|
||||
pool = Pool()
|
||||
Reference = pool.get('test.reference_context')
|
||||
Target = pool.get('test.reference_context.target')
|
||||
|
||||
target, = Target.create([{}])
|
||||
record, = Reference.create([{
|
||||
'target': str(target),
|
||||
}])
|
||||
data, = Reference.read([record.id], ['target.context'])
|
||||
|
||||
self.assertEqual(data['target.']['context'], 'foo')
|
||||
|
||||
@with_transaction()
|
||||
def test_context_set(self):
|
||||
"Test context on reference set"
|
||||
pool = Pool()
|
||||
Reference = pool.get('test.reference_context')
|
||||
Target = pool.get('test.reference_context.target')
|
||||
|
||||
target, = Target.create([{}])
|
||||
record = Reference(target=str(target))
|
||||
|
||||
self.assertEqual(record.target.context, 'foo')
|
||||
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromTestCase(FieldReferenceTestCase)
|
||||
|
||||
Reference in New Issue
Block a user