python Django Django排序,总是先为零,然后为正,然后为负

时间:2018-12-03 22:23:14

标签: python django python-3.x

我将Django对象设置为:

class Example(models.Model):
    count = models.CharField(default="0")

因此,如果我有一些对象ex1ex2ex3ex4,其计数分别为-1、0、5,-6。我希望能够查询对象并将它们按[0, 5, -6, -1]的顺序进行排序,其中任何零先出现,然后是正数,然后是负数,同时每个部分也按升序排列。我当时正在考虑使用类似Example.objects.order_by('count')的东西,但是找不到一种使用诸如this这样的自定义函数的方法。

我正在寻找的另一条路线如下:

objs = Example.objects.all()
sorted_objs = sorted(objs, key = lambda o: int(o.count))

有没有一种方法可以使用sorted方法首先对零进行排序?我找不到一个。

我使用的最后一种方法是:

objs = Example.objects.all()
zero_objs = []
positive_objs = []
negative_objs = []
for obj in objs:
    if obj.count == 0:
        zero_objs.append(obj)
    elif obj.count < 0:
        negative_objs.append(obj)
    else:
        postitive_objs.append(obj)
sorted_objs = zero_objs + sorted(postitive_objs) + sorted(negative_objs)

这可行,但似乎并不是实现此目的的最佳方法,因此任何想法都很棒。附带说明一下,我知道count属性最好存储为整数字段,但是我想在保留char字段的同时完成此操作。

1 个答案:

答案 0 :(得分:3)

您可以使用case添加新字段以进行订购:

>>> from django.db.models import Case, IntegerField, Value, When
>>> Example.objects.annotate(
...     o=Case(
...         When(count=0, then=Value(0),
...         When(count__gt=0, then=Value(1)),
...         When(count__lt=0, then=Value(2)),
...         output_field=IntegerField(),
...     ),
... ).order_by('o', 'count')

说明:

Order子句将由以下两者组成:“新字段” count。使用“新字段”,您可以将count = 0的行集提高到顶部,然后在最后一组负数处集正数。第二个字段count对每个集合进行升序排序。

免责声明:

请注意,这不是索引友好的解决方案!如果需要性能,则只需在模型上创建此新字段,然后在保存之前先弄清楚该字段。