查询集排序:为 django ORM 查询指定列排序规则

Posted

技术标签:

【中文标题】查询集排序:为 django ORM 查询指定列排序规则【英文标题】:Queryset sorting: Specifying column collation for django ORM query 【发布时间】:2013-09-26 23:02:19 【问题描述】:

我开始调查为什么我的 Django Model.objects.filter(condition = variable).order_by(textcolumn) 查询不能以正确的顺序生成对象。发现是数据库(Postgresql)的问题。

在我之前的问题 (Postgresql sorting language specific characters (collation)) 中,我发现(在 zero323 的大力帮助下,我可以真正让它工作)我可以像这样为每个数据库查询指定排序规则:

SELECT nimi COLLATE "et_EE" FROM test ORDER BY nimi ASC;

但据我所知,order_by 只接受字段名称作为参数。

我想知道,是否可以通过某种方式扩展该功能以包含排序规则参数?是否有可能使用 mixins 或诸如此类的东西以某种方式破解它?还是功能请求是目前唯一的方法?

我希望它能像这样工作:

Model.objects.filter(condition = variable).order_by(*fieldnames, collation = 'et_EE')

编辑1: 显然我不是唯一一个要求这个的人: https://groups.google.com/forum/#!msg/django-developers/0iESVnawNAY/JefMfAm7nQMJ

艾伦

【问题讨论】:

如需就如何改进 Django 提出建议,请提交new feature request 和/或在django-developers 上发帖。现在你可能不得不使用raw SQL query。 嗯,是的,谢谢。我想/将要求该功能。我只想先知道,是否可以使用现有工具实现它。毫无疑问,Raw Query 就是其中之一。 【参考方案1】:

由于 Django 1.8 order_by() 不仅接受字段名称but also query expressions。

在another answer 中,我举例说明了如何覆盖列的默认排序规则。这里有用的查询表达式是Func(),您可以继承或直接使用它:

nimi_et = Func(
    'nimi',
    function='et_EE',
    template='(%(expressions)s) COLLATE "%(function)s"')
Test.objects.order_by(nimi_et.asc())

但请注意,生成的 SQL 将更像:

SELECT nimi FROM test ORDER BY nimi COLLATE "et_EE" ASC;

也就是说,排序规则在ORDER BY 子句中被覆盖,而不是在SELECT 子句中。但是,如果您需要在WHERE 子句中使用它,您可以在annotate() 中使用Func()

【讨论】:

请注意,在ORDER BY 中设置排序规则会阻止使用任何原本适用的索引。【参考方案2】:

好的。现在看来,原始查询是做到这一点的唯一方法。

但是有 django ticket open 希望很快就会关闭/解决。

【讨论】:

以上是关于查询集排序:为 django ORM 查询指定列排序规则的主要内容,如果未能解决你的问题,请参考以下文章

Django ORM数据库查询操作

Django ORM 按过滤器排序

Django ORM查询,不同的值并加入同一张表

Django查询集QuerySet及两大特性

如何在 Django ORM 中更改 PostgreSQL 的默认空排序行为

使用 ORM Django 过滤新更新的查询集返回空查询集