Add translated descriptor for Dict field
issue4343 review11641002
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
* Add translated descriptor for Dict field
|
||||
* Clean private context keyword in RPC
|
||||
* Add cache section in configuration
|
||||
* Use dualmethod on ModelStorage.save
|
||||
|
||||
@@ -770,3 +770,11 @@ A dictionary field with predefined keys.
|
||||
|
||||
The name of the :class:`DictSchemaMixin` model that stores the definition
|
||||
of keys.
|
||||
|
||||
Instance methods:
|
||||
|
||||
.. method:: Dict.translated([name[, type_]])
|
||||
|
||||
Returns a descriptor for the translated `values` or `keys` of the field
|
||||
following `type_`. The descriptor must be used on the same class as the
|
||||
field. Default `type_` is `values`.
|
||||
|
||||
@@ -8,6 +8,8 @@ from sql import Query, Expression
|
||||
|
||||
from .field import Field, SQLType
|
||||
from ...protocols.jsonrpc import JSONDecoder, JSONEncoder
|
||||
from ...pool import Pool
|
||||
from ...tools import grouped_slice
|
||||
|
||||
|
||||
class Dict(Field):
|
||||
@@ -42,3 +44,50 @@ class Dict(Field):
|
||||
|
||||
def sql_type(self):
|
||||
return SQLType('TEXT', 'TEXT')
|
||||
|
||||
def translated(self, name=None, type_='values'):
|
||||
"Return a descriptor for the translated value of the field"
|
||||
if name is None:
|
||||
name = self.name
|
||||
if name is None:
|
||||
raise ValueError('Missing name argument')
|
||||
return TranslatedDict(name, type_)
|
||||
|
||||
|
||||
class TranslatedDict(object):
|
||||
'A descriptor for translated values of Dict field'
|
||||
|
||||
def __init__(self, name, type_):
|
||||
assert type_ in ['keys', 'values']
|
||||
self.name = name
|
||||
self.type_ = type_
|
||||
|
||||
def __get__(self, inst, cls):
|
||||
if inst is None:
|
||||
return self
|
||||
pool = Pool()
|
||||
schema_model = getattr(cls, self.name).schema_model
|
||||
SchemaModel = pool.get(schema_model)
|
||||
|
||||
value = getattr(inst, self.name)
|
||||
if not value:
|
||||
return value
|
||||
|
||||
domain = []
|
||||
if self.type_ == 'values':
|
||||
domain = [('type_', '=', 'selection')]
|
||||
|
||||
records = []
|
||||
for key_names in grouped_slice(value.keys()):
|
||||
records += SchemaModel.search([
|
||||
('name', 'in', key_names),
|
||||
] + domain)
|
||||
keys = SchemaModel.get_keys(records)
|
||||
|
||||
if self.type_ == 'keys':
|
||||
return {k['name']: k['string'] for k in keys}
|
||||
|
||||
elif self.type_ == 'values':
|
||||
trans = {k['name']: dict(k['selection']) for k in keys}
|
||||
return {k: v if k not in trans else trans[k].get(v, v)
|
||||
for k, v in value.iteritems()}
|
||||
|
||||
@@ -89,6 +89,7 @@ def register():
|
||||
Property,
|
||||
Selection,
|
||||
SelectionRequired,
|
||||
DictSchema,
|
||||
Dict,
|
||||
DictDefault,
|
||||
DictRequired,
|
||||
|
||||
+10
-3
@@ -3,7 +3,7 @@
|
||||
|
||||
import datetime
|
||||
from decimal import Decimal
|
||||
from trytond.model import ModelSQL, fields
|
||||
from trytond.model import ModelSQL, DictSchemaMixin, fields
|
||||
from trytond.pyson import Eval
|
||||
|
||||
__all__ = [
|
||||
@@ -32,7 +32,7 @@ __all__ = [
|
||||
'Reference', 'ReferenceTarget', 'ReferenceRequired',
|
||||
'Property',
|
||||
'Selection', 'SelectionRequired',
|
||||
'Dict', 'DictDefault', 'DictRequired',
|
||||
'DictSchema', 'Dict', 'DictDefault', 'DictRequired',
|
||||
'Binary', 'BinaryDefault', 'BinaryRequired',
|
||||
'Many2OneDomainValidation', 'Many2OneTarget',
|
||||
]
|
||||
@@ -629,10 +629,17 @@ class SelectionRequired(ModelSQL):
|
||||
'Selection', required=True)
|
||||
|
||||
|
||||
class DictSchema(DictSchemaMixin, ModelSQL):
|
||||
'Dict Schema'
|
||||
__name__ = 'test.dict.schema'
|
||||
|
||||
|
||||
class Dict(ModelSQL):
|
||||
'Dict'
|
||||
__name__ = 'test.dict'
|
||||
dico = fields.Dict(None, 'Test Dict')
|
||||
dico = fields.Dict('test.dict.schema', 'Test Dict')
|
||||
dico_string = dico.translated('dico')
|
||||
dico_string_keys = dico.translated('dico', 'keys')
|
||||
|
||||
|
||||
class DictDefault(ModelSQL):
|
||||
|
||||
@@ -102,6 +102,7 @@ class FieldsTestCase(unittest.TestCase):
|
||||
self.selection_required = POOL.get('test.selection_required')
|
||||
|
||||
self.dict_ = POOL.get('test.dict')
|
||||
self.dict_schema = POOL.get('test.dict.schema')
|
||||
self.dict_default = POOL.get('test.dict_default')
|
||||
self.dict_required = POOL.get('test.dict_required')
|
||||
|
||||
@@ -3108,6 +3109,23 @@ class FieldsTestCase(unittest.TestCase):
|
||||
'Test Dict'
|
||||
with Transaction().start(DB_NAME, USER,
|
||||
context=CONTEXT) as transaction:
|
||||
|
||||
self.dict_schema.create([{
|
||||
'name': 'a',
|
||||
'string': 'A',
|
||||
'type_': 'integer',
|
||||
}, {
|
||||
'name': 'b',
|
||||
'string': 'B',
|
||||
'type_': 'integer',
|
||||
}, {
|
||||
'name': 'type',
|
||||
'string': 'Type',
|
||||
'type_': 'selection',
|
||||
'selection': ('arabic: Arabic\n'
|
||||
'hexa: Hexadecimal'),
|
||||
}])
|
||||
|
||||
dict1, = self.dict_.create([{
|
||||
'dico': {'a': 1, 'b': 2},
|
||||
}])
|
||||
@@ -3116,6 +3134,21 @@ class FieldsTestCase(unittest.TestCase):
|
||||
self.dict_.write([dict1], {'dico': {'z': 26}})
|
||||
self.assert_(dict1.dico == {'z': 26})
|
||||
|
||||
dict1.dico = {
|
||||
'a': 1,
|
||||
'type': 'arabic',
|
||||
}
|
||||
dict1.save()
|
||||
self.assertEqual(dict1.dico, {'a': 1, 'type': 'arabic'})
|
||||
self.assertEqual(dict1.dico_string, {
|
||||
'a': 1,
|
||||
'type': 'Arabic',
|
||||
})
|
||||
self.assertEqual(dict1.dico_string_keys, {
|
||||
'a': 'A',
|
||||
'type': 'Type',
|
||||
})
|
||||
|
||||
dict2, = self.dict_.create([{}])
|
||||
self.assert_(dict2.dico is None)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user