对于项目库,用户可以手动对某些项目进行排序,以使它们首先出现。
为此,模型的“排序”不是空的PositiveIntegerField(默认为0)。排序字段大于零的项目是手动排序的,必须出现在排序值为0的未排序项目之前。
可以使用的SQL查询可能是这样的:
(select photo, sort, 0 as priority from photos where sort > 0)
union all
(select photo, sort, 1 as priority from photos where sort = 0)
order by priority, sort
结果如下:
+---------+------+----------+
| photo | sort | priority |
+---------+------+----------+
| photo-a | 1 | 0 |
| photo-b | 2 | 0 |
| photo-c | 0 | 1 |
| photo-d | 0 | 1 |
| photo-e | 0 | 1 |
| ... |
但我无法弄清楚如何使用Django Queryset正确完成它?
我能够将两个不同的查询集与list(chain(q1, q2))
合并,但是执行查询,这对于大型集合来说效率很低,特别是如果我的查询集应该传递给通常会应用LIMIT的django.core.paginator分页的OFFSET子句。当然,我可以对每个查询q1
和q2
应用切片,但这有点难看,因为它与分页器的重叠。
也许我试图以错误的方式去做。或者也许应该使用extra()方法完成?
答案 0 :(得分:1)
执行查询集的联合/合并不是解决方案。更简单的解决方案是在订单声明中使用比较。 stackeoverflow上的answer向我指出了这个简洁的解决方案。
select * from photos order by sort=0, sort
0 = 0被评估为True,等于1,1 = 0是False,等于0等等吗?
转换为Django Queryset:
Photos.objects.extra(select={'sortiszero': 'sort = 0'}, order_by=['sortiszero', 'sort'])
结果:
+---------+------+
| photo | sort |
+---------+------+
| photo-a | 1 |
| photo-b | 2 |
| photo-c | 0 |
| photo-d | 0 |
| photo-e | 0 |
| ... |
瞧!
答案 1 :(得分:0)
你应该提供更多细节。
如果你想结合这两套,你可以简单地添加列表:
list1 = SomeModel.objects.filter(sort != 0).order_by('column_name_1','column_name_2')
list2 = SomeModel.objects.filter(sort = 0).order_by('priority','foo')
return list = list1 + list2
或者如果你想使用extra()方法,这里有一个问题:
list = SomeModel.objects.fooMethod().extra(order_by=[foo,])