Group records when calling set method for field with the same value

We need to loop to compare the values instead of using a dictionary because the
values are not necessary hashable. But it is still an improvement compared to
calling the set method for each record.

issue5398
review19111002
This commit is contained in:
Cédric Krier
2016-03-19 12:07:27 +01:00
parent 1380d60c45
commit 23c45fc511
4 changed files with 58 additions and 3 deletions
+8 -2
View File
@@ -576,8 +576,14 @@ class ModelSQL(ModelStorage):
translation_values.setdefault(
'%s,%s' % (cls.__name__, fname), {})[new_id] = value
if hasattr(field, 'set'):
fields_to_set.setdefault(fname, []).extend(
([new_id], value))
args = fields_to_set.setdefault(fname, [])
actions = iter(args)
for ids, val in zip(actions, actions):
if val == value:
ids.append(new_id)
break
else:
args.extend(([new_id], value))
if translation_values:
for name, translations in translation_values.iteritems():
+1
View File
@@ -106,6 +106,7 @@ def register():
ModelStorage,
ModelSQLRequiredField,
ModelSQLTimestamp,
ModelSQLFieldSet,
Model4Union1,
Model4Union2,
Model4Union3,
+16 -1
View File
@@ -5,7 +5,7 @@ from trytond.model import ModelSingleton, ModelSQL, UnionMixin, fields
__all__ = [
'Singleton', 'URLObject',
'ModelStorage',
'ModelSQLRequiredField', 'ModelSQLTimestamp',
'ModelSQLRequiredField', 'ModelSQLTimestamp', 'ModelSQLFieldSet',
'Model4Union1', 'Model4Union2', 'Model4Union3', 'Model4Union4',
'Union', 'UnionUnion',
'Model4UnionTree1', 'Model4UnionTree2', 'UnionTree',
@@ -47,6 +47,21 @@ class ModelSQLTimestamp(ModelSQL):
__name__ = 'test.modelsql.timestamp'
class ModelSQLFieldSet(ModelSQL):
'Model to test field set'
__name__ = 'test.modelsql.field_set'
field = fields.Function(fields.Integer('Field'),
'get_field', setter='set_field')
def get_field(self, name=None):
return
@classmethod
def set_field(cls, records, name, value):
pass
class Model4Union1(ModelSQL):
'Model for union 1'
__name__ = 'test.model.union1'
+33
View File
@@ -5,6 +5,8 @@
import unittest
import time
from mock import patch, call
from trytond import backend
from trytond.exceptions import UserError, ConcurrencyException
from trytond.transaction import Transaction
@@ -81,6 +83,37 @@ class ModelSQLTestCase(unittest.TestCase):
ModelsqlTimestamp.delete([record])
transaction.commit()
@with_transaction()
def test_create_field_set(self):
'Test field.set in create'
pool = Pool()
Model = pool.get('test.modelsql.field_set')
with patch.object(Model, 'set_field') as setter:
records = Model.create([{'field': 1}])
setter.assert_called_with(records, 'field', 1)
# Different values are not grouped
with patch.object(Model, 'set_field') as setter:
records = Model.create([{'field': 1}, {'field': 2}])
setter.assert_has_calls([
call([records[0]], 'field', 1),
call([records[1]], 'field', 2),
])
# Same values are grouped in one call
with patch.object(Model, 'set_field') as setter:
records = Model.create([{'field': 1}, {'field': 1}])
setter.assert_called_with(records, 'field', 1)
# Mixed values are grouped per value
with patch.object(Model, 'set_field') as setter:
records = Model.create([{'field': 1}, {'field': 2}, {'field': 1}])
setter.assert_has_calls([
call([records[0], records[2]], 'field', 1),
call([records[1]], 'field', 2),
])
def suite():
return unittest.TestLoader().loadTestsFromTestCase(ModelSQLTestCase)