我的模型有一个字段(让我们称之为this_field
),它存储为string
。 this_field
中的值采用Char###
形式,因为它们的值包括:A4
或A34
或A55
(请注意,它们始终为有相同的第一个字符)。
有没有办法选择所有记录并按此字段排序?目前,当我执行.order_by('this_field')
时,我得到了这样的订单:
A1
A13
A2
A25
等...
我想要的是:
A1
A2
A13
A25
等...
实现此查询集的任何最佳方法或解决方案是否正确排序?
答案 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)
如果您经常使用此排序顺序,则应考虑包含分隔值的两个单独字段:
db_index=True
设置db_index=True
。 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:]))