当Odoo搜索记录时,它会尝试基于order_spec构造一个合适的ORDER BY clause,该ORDER BY clause必须是一个逗号分隔的有效字段名列表,可选后跟ASC或DESC方向.
order by 子句是根据_order 属性计算的,并且可以被搜索函数中的order 参数覆盖。
您可以覆盖_generate_order_by_inner 函数,以便可以直接在char 字段的_order 属性(field_name:function) 中传递SQL 查询中使用的函数名称。
示例:
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
您还可以修补 models.BaseModel._generate_order_by_inner 以对任何字符字段使用相同的逻辑。
示例:
@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
要覆盖任何视图中的排序顺序,您只需包括:
if field.type == 'char':
qualifield_name = "lower(%s)" % (qualifield_name,)
无需重新定义顺序。