Allow to use the dotted notation for search order parameters

issue4370
review5801002
This commit is contained in:
Nicolas Évrard committed 2015-01-02 16:33:00 +01:00
1 parent 67d5291bfd
commit dcf57d8c33
7 files changed
+57 -15

No files matched your search

+1
View File
@@ -1,3 +1,4 @@
* Allow to use the dotted notation for order parameters
* Use action_id to find report to use
* Allow custom StateView without Model
* Remove Pool.object_name_list
+4
View File
@@ -367,6 +367,10 @@ Class attributes are:
second is the sort ordering as `ASC` for ascending or `DESC` for
descending.
In case the field used for the first element is a :class:`fields.Many2One`,
it is also possible to use the dotted notation to sort on a specific field
from the target record.
.. attribute:: ModelSQL._order_name
The name of the field (or an SQL statement) on which the records must be
+20 -12
View File
@@ -180,25 +180,33 @@ class Many2One(Field):
return column.in_(query)
def convert_order(self, name, tables, Model):
if getattr(Model, 'order_%s' % name, None):
return super(Many2One, self).convert_order(name, tables, Model)
assert name == self.name
fname, _, oexpr = name.partition('.')
if not oexpr and getattr(Model, 'order_%s' % fname, None):
return super(Many2One, self).convert_order(fname, tables, Model)
assert fname == self.name
Target = self.get_target()
oname = 'id'
if Target._rec_name in Target._fields:
oname = Target._rec_name
if Target._order_name in Target._fields:
oname = Target._order_name
if oexpr:
oname, _, _ = oexpr.partition('.')
else:
oname = 'id'
if Target._rec_name in Target._fields:
oname = Target._rec_name
if Target._order_name in Target._fields:
oname = Target._order_name
oexpr = oname
table, _ = tables[None]
if oname == 'id':
return [self.sql_column(table)]
ofield = Target._fields[oname]
table, _ = tables[None]
target_tables = tables.get(name)
target_tables = tables.get(fname)
if target_tables is None:
target = Target.__table__()
target_tables = {
None: (target, target.id == self.sql_column(table)),
}
tables[name] = target_tables
return ofield.convert_order(oname, target_tables, Target)
tables[fname] = target_tables
return ofield.convert_order(oexpr, target_tables, Target)
+3 -2
View File
@@ -997,10 +997,11 @@ class ModelSQL(ModelStorage):
}
if order is None or order is False:
order = cls._order
for fname, otype in order:
for oexpr, otype in order:
fname, _, extra_expr = oexpr.partition('.')
field = cls._fields[fname]
Order = order_types[otype.upper()]
forder = field.convert_order(fname, tables, cls)
forder = field.convert_order(oexpr, tables, cls)
order_by.extend((Order(o) for o in forder))
main_table, _ = tables[None]
+1
View File
@@ -154,6 +154,7 @@ def register():
CopyMany2ManyReferenceRelation,
Many2OneTarget,
Many2OneDomainValidation,
Many2OneOrderBy,
TestHistory,
TestHistoryLine,
FieldContextChild,
+8 -1
View File
@@ -34,7 +34,7 @@ __all__ = [
'Selection', 'SelectionRequired',
'DictSchema', 'Dict', 'DictDefault', 'DictRequired',
'Binary', 'BinaryDefault', 'BinaryRequired',
'Many2OneDomainValidation', 'Many2OneTarget',
'Many2OneDomainValidation', 'Many2OneTarget', 'Many2OneOrderBy',
]
@@ -683,6 +683,7 @@ class BinaryRequired(ModelSQL):
class Many2OneTarget(ModelSQL):
"Many2One Domain Validation Target"
__name__ = 'test.many2one_target'
_order_name = 'value'
active = fields.Boolean('Active')
value = fields.Integer('Value')
@@ -701,3 +702,9 @@ class Many2OneDomainValidation(ModelSQL):
('value', '>', 5),
])
dummy = fields.Char('Dummy')
class Many2OneOrderBy(ModelSQL):
"Many2One OrderBy"
__name__ = 'test.many2one_orderby'
many2one = fields.Many2One('test.many2one_target', 'many2one')
+20
View File
@@ -111,6 +111,7 @@ class FieldsTestCase(unittest.TestCase):
self.binary_required = POOL.get('test.binary_required')
self.m2o_domain_validation = POOL.get('test.many2one_domainvalidation')
self.m2o_orderby = POOL.get('test.many2one_orderby')
self.m2o_target = POOL.get('test.many2one_target')
def test0010boolean(self):
@@ -3236,6 +3237,25 @@ class FieldsTestCase(unittest.TestCase):
domain.dummy = 'Dummy'
domain.save()
# Testing order_by
for value in (5, 3, 2):
m2o, = self.m2o_target.create([{'value': value}])
self.m2o_orderby.create([{'many2one': m2o}])
search = self.m2o_orderby.search([], order=[('many2one', 'ASC')])
self.assertTrue(all(x.many2one.value <= y.many2one.value
for x, y in zip(search, search[1:])))
search = self.m2o_orderby.search([],
order=[('many2one.id', 'ASC')])
self.assertTrue(all(x.many2one.id <= y.many2one.id
for x, y in zip(search, search[1:])))
search = self.m2o_orderby.search([],
order=[('many2one.value', 'ASC')])
self.assertTrue(all(x.many2one.value <= y.many2one.value
for x, y in zip(search, search[1:])))
transaction.cursor.rollback()