2013-03-18 25 views
2

我有一个模型有一个字段(我们称之为this_field),它存储为stringthis_field中的值的格式为Char###,因为它们的值为:A4A34A55(请注意,它们始终具有相同的第一个字符)。django - 具有字符和整数的queryset order_by字段

有没有一种方法来选择所有记录,并通过此字段顺序呢?目前,当我做一个.order_by('this_field')我得到的命令是这样的:

A1 A13 A2 A25 等等

我要的是:

A1 A2 A13 A25 etc ...

任何最好的方法方法或解决方案,以实现有序的正确此查询集?

回答

3

queryset的顺序是由数据库后端处理,而不是由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()调用中只指定一个字段。

+0

完美的工作。尽管我不知道你是否编辑了你的答案在某处添加了一个额外的封闭支架......我不得不添加一个。尽管如此,像一个魅力工作!谢谢 :) – Garfonzo 2013-03-18 01:32:19

1

这样做是基于对this_field的INT部分查询集进行排序的另一种方式:

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

如果使用这种排序顺序了很多,在更大的表,你应该认为包含约两个独立的领域分离出的值:

  1. 阿尔法值应该仅小写,在文本或字符字段中,与db_index=True设置
  2. 的数值应该是一个整数字段db_index=True设置在它们上面。

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

否则你可能会遇到一些(或最多一个巨大的)性能的影响。