【问题标题】:django - queryset order_by field that has characters and integersdjango - 具有字符和整数的查询集 order_by 字段
【发布时间】:2013-03-18 00:13:53
【问题描述】:

我有一个模型,它有一个存储为string 的字段(我们称之为this_field)。 this_field 中的值采用 Char### 的形式 - 如,它们具有以下值:A4A34A55(请注意,它们将始终具有相同的第一个字符)。

有没有办法选择所有记录并按此字段排序?目前,当我执行.order_by('this_field') 时,我会收到这样的订单:

A1 A13 A2 A25 等等……

我想要的是:

A1 A2 A13 A25 等等……

是否有任何最佳方法或解决方案来实现此查询集的正确排序?

【问题讨论】:

    标签: django django-queryset


    【解决方案1】:

    查询集排序由数据库后端处理,而不是由 Django。这限制了更改排序方式的选项。您可以加载所有数据并使用 Python 对其进行排序,也可以在查询中添加其他选项以使数据库通过定义函数来使用某种自定义排序。

    使用查询集extra() 函数将允许您通过执行自定义 SQL 进行排序来做您想做的事情,但代价是降低了可移植性。

    在您的示例中,将输入字段拆分为两组数据可能就足够了,即初始字符和剩余的整数值。然后,您可以对两列应用排序。这是一个示例(未经测试):

    qs = MyModel.objects.all()
    
    # Add in a couple of extra SELECT columns, pulling apart this_field into
    # this_field_a (the character portion) and this_field_b (the integer portion).
    
    qs = qs.extra(select={
                  'this_field_a': "SUBSTR(this_field, 1)",
                  'this_field_b': "CAST(substr(this_field, 2) AS UNSIGNED)"})
    

    extra 调用将两个新字段添加到 SELECT 调用中。第一个子句提取字段的第一个字符,第二个子句将字段的其余部分转换为整数。

    现在应该可以在这些字段上order_by。通过为order_by 指定两个字段,排序首先适用于字符字段,然后适用于整数字段。

    例如

    qs = qs.order_by('this_field_a', 'this_field_b')
    

    这个例子应该适用于 MySql 和 SQLite。还应该可以创建一个仅用于排序的额外字段,允许您在 order_by() 调用中仅指定一个字段。

    【讨论】:

    • 效果很好。虽然我想知道您是否编辑了答案以在某处添加一个额外的封闭括号...我不得不添加一个。尽管如此,工作就像一个魅力!谢谢:)
    【解决方案2】:

    如果您经常使用这种排序顺序并且在较大的表上,您应该考虑两个包含分隔值的单独字段:

    1. alpha 值只能在文本或字符字段中小写,并设置db_index=True
    2. 数值应位于一个整数字段中,并在其上设置db_index=True

    qs.order_by('alpha_sort_field', 'numeric_sort_field')

    否则,您可能会遇到一些(或最大的)性能影响。

    【讨论】:

      【解决方案3】:

      另一种方法是根据this_field的int部分对QuerySet进行排序:

      qs = ModelClass.objects.all()
      sorted_qs = sorted(qs, key=lambda ModelClass: int(ModelClass.this_field[1:]))
      

      【讨论】:

        猜你喜欢
        • 2019-07-14
        • 2021-08-30
        • 1970-01-01
        • 2011-03-10
        • 1970-01-01
        • 1970-01-01
        • 2018-10-06
        • 2012-04-07
        • 1970-01-01
        相关资源
        最近更新 更多