django - queryset order_by包含字符和整数的字段

时间:2013-03-18 00:13:54

标签: django django-queryset

我的模型有一个字段(让我们称之为this_field),它存储为stringthis_field中的值采用Char###形式,因为它们的值包括:A4A34A55(请注意,它们始终为有相同的第一个字符)。

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

A1 A13 A2 A25 等...

我想要的是:

A1 A2 A13 A25 等...

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

3 个答案:

答案 0 :(得分:3)

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

使用queryset 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()调用中仅指定一个字段。

答案 1 :(得分:2)

如果您经常使用此排序顺序,则应考虑包含分隔值的两个单独字段:

  1. db_index=True设置
  2. 的文本或字段中,alpha值应仅小写
  3. 数值应位于整数字段中,并设置db_index=True
  4. qs.order_by('alpha_sort_field', 'numeric_sort_field')

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

答案 2 :(得分:1)

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

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