在Django中为查询集执行手动排序

时间:2017-12-20 19:04:50

标签: django

我正在使用Django 1.11,我试图找到一种方法来手动更改查询集的顺序。这是我的设置:

models.py

class Channel(models.Model):
    channel_no = models.CharField(max_length=4, unique=True)

    def __str__(self):
        return self.channel_no

我有一系列我希望用于订单的频道号码:

channel_order = ['2','4','6','8','10','1','3','5','7','9']

如何将该订单用于查询集?

我知道在MySQL中你可以通过在Select语句中使用 field 来实现这一点。这是一个例子:

SELECT * FROM Channel
ORDER BY FIELD(`channel_no`,'2','4','6','8','10','1','3','5','7','9') 

1 个答案:

答案 0 :(得分:0)

如果您的订购是奇数channel_no,那么即使我有下一个解决方案。

from django.db.models import Func, F, IntegerField

qs = Channel.objects.annotate(
    channel_no_as_int=Cast(F('channel_no'), IntegerField()),
    ordering=Func(F('channel_no_as_int'), 2, function='Mod') * 5000 + F(
        'channel_no_as_int')).order_by('ordering')

因为你有max_length = 4然后max channel_no等于9999这意味着可能有最大5000偶数和5000奇数,所以我采用乘数= 5000移动奇数(mod(数字,2)== 1)

更新

由于您需要用户定义的自定义排序,因此您可以实现此目标:

order = '2', '4', '6', '8', '10', '1', '3', '5', '7', '9'
order = map(Value, order)
qs = Channel.objects.annotate(
    ordering=Func('channel_no', *order, function='FIELD')).order_by('ordering')