2

我有一个模型,它有一个this_field存储为string. 中的值this_field采用格式Char###- 就像在中一样,它们具有以下值:A4A34A55(请注意,它们将始终具有相同的第一个字符)。

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

A1 A13 A2 A25 ETC...

我想要的是:

A1 A2 A13 A25 ETC...

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

4

3 回答 3

3

查询集排序由数据库后端处理,而不是由 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()调用中仅指定一个字段。

于 2013-03-18T01:07:25.137 回答
2

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

  1. alpha 值应仅小写,在文本或字符字段中,db_index=True设置
  2. 数值应该在一个整数字段中,db_index=True并对其进行设置。

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

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

于 2016-01-18T15:26:38.863 回答
1

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

qs = ModelClass.objects.all()
sorted_qs = sorted(qs, key=lambda ModelClass: int(ModelClass.this_field[1:]))
于 2013-03-18T01:45:50.270 回答