Reputation: 175
My use-case is to list the records in a tree or kanban view by name but it should be case insensitive. Current state Eg. I have four records like
Apple
Orange
apple
Banana
In default the ordering is:
Apple
Banana
Orange
apple
And the expected ordering is:
Apple
apple
Banana
Orange
How to achieve this? Is there any ORM method to do this?
Upvotes: 0
Views: 1396
Reputation: 26718
When Odoo searches for records, it will attempt to construct an appropriate ORDER BY clause
based on order_spec
, which must be a comma-separated list of valid field names, optionally followed by an ASC
or DESC
direction.
The order by clause is computed based on _order attribute and can be overridden by the order
parameter in the search function.
You can override the _generate_order_by_inner
function to make it possible to pass function names used in SQL queries directly in _order
attribute (field_name:function
) for char fields.
Example:
class Fruits(models.Model):
_name = 'fruit.fruit'
_order = 'name:lower'
name = fields.Char()
@api.model
def _generate_order_by_inner(self, alias, order_spec, query, reverse_direction=False, seen=None):
if seen is None:
seen = set()
self._check_qorder(order_spec)
order_by_elements = []
for order_part in order_spec.split(','):
order_split = order_part.strip().split(' ')
order_field = order_split[0].strip()
order_direction = order_split[1].strip().upper() if len(order_split) == 2 else ''
if reverse_direction:
order_direction = 'ASC' if order_direction == 'DESC' else 'DESC'
do_reverse = order_direction == 'DESC'
# ------------------------------------------------------------------
func_split = order_field.strip().split(':')
order_field = func_split[0].strip()
func = func_split[1].strip().upper() if len(func_split) == 2 else ''
# ------------------------------------------------------------------
field = self._fields.get(order_field)
if not field:
raise ValueError("Invalid field %r on model %r" % (order_field, self._name))
if order_field == 'id':
order_by_elements.append('"%s"."%s" %s' % (alias, order_field, order_direction))
else:
if field.inherited:
field = field.base_field
if field.store and field.type == 'many2one':
key = (field.model_name, field.comodel_name, order_field)
if key not in seen:
seen.add(key)
order_by_elements += self._generate_m2o_order_by(alias, order_field, query, do_reverse, seen)
elif field.store and field.column_type:
qualifield_name = self._inherits_join_calc(alias, order_field, query)
if field.type == 'boolean':
qualifield_name = "COALESCE(%s, false)" % qualifield_name
# ------------------------------------------------------
if func and field.type == 'char':
qualifield_name = "%s(%s)" % (func, qualifield_name)
# ------------------------------------------------------
order_by_elements.append("%s %s" % (qualifield_name, order_direction))
else:
_logger.warning("Model %r cannot be sorted on field %r (not a column)", self._name, order_field)
continue # ignore non-readable or "non-joinable" fields
return order_by_elements
You can also patch the models.BaseModel._generate_order_by_inner
to use the same logic for any char field.
Example:
@api.model
def _generate_order_by_inner(self, alias, order_spec, query, reverse_direction=False, seen=None):
...
models.BaseModel._generate_order_by_inner = _generate_order_by_inner
To override the sort order in any view, you have just to include:
if field.type == 'char':
qualifield_name = "lower(%s)" % (qualifield_name,)
Without redefining the order.
Upvotes: 2
Reputation: 14778
You have to think atleast about two things:
Using search
(or search_count
) to get records from the database. You can use the parameter order
to tell Odoo which order the records should be get directly sorted by the database. So for example use self.env['fruits'].search([], order="LOWER(name)")
to get all fruits in "true" alphabetically order on column "name".
The second part to think about is sorting records in python. But the same principal can be used there. Just lower- or uppercase while sorting.
A third part could be direct queries, but using them in this context would be the same like doing the "search" from point 1. Because the order
parameter will be set in the query Odoo is building in the end of search
anyways.
Upvotes: 0