按升序排序Django查询集,但最后使用0值项

时间:2015-10-20 11:09:58

标签: python django sorting django-queryset django-orm

我是python,django的新手。我想要做的是我将模型定义为具有两列的产品:名称和价格。

name    price
pen      20
paper    30
eraser   0

我正在尝试使用以下代码对它们进行排序:

Product.objects.all().order_by('-price')

将值排序为0,20,30

型号代码是

class Product(models.Model):
    name = models.CharField(max_length=100, blank=True, null=True)
    price = models.IntegerField('Price', blank=True, null=True)

我想要实现的是将其排序为20,30,0,并在末尾添加0。

我能用它实现任何功能吗?

4 个答案:

答案 0 :(得分:7)

如果确实想要在数据库级别执行所有操作,您可以按计算值排序。这应该有效:

Product.objects.all().order_by(\
        Case(When(price=0, then=Value(MAX_INT)), default=F('price')))

其中MAX_INT=2147483647是32位有符号整数的值safe on all Django-supported DBs

答案 1 :(得分:4)

以下可能有效,它不是最好的代码实现,但对于您的特殊情况,我认为这是使用queryset直接执行它的简单方法,否则您可以考虑在Python中实现它(已排序或其他内置函数)

qs = Product.objects.exclude(price=0).order_by('-price') | Product.objects.filter(price=0)

答案 2 :(得分:1)

您想要实现的是此SQL查询:

SELECT * FROM product ORDER BY price = 0, price;

使用Django的ORM,使用extra()过滤器修饰符:

Product.objects.extra(select={"custom":"price = 0"}, order_by=["custom","price"]).all()

答案 3 :(得分:1)

  

Conditional Expressions允许您在过滤器,注释,聚合和更新中使用if ... elif ... else逻辑。条件表达式为表的每一行计算一系列条件,并返回匹配的结果表达式。

from django.db.models import IntegerField, Case, Value, When

MAX_INT = 2147483647
Product.objects.annotate(
    my_price=Case(
        When(price=0, then=Value(MAX_INT)),
        default='price',
        output_field=IntegerField(),
    )
).order_by('my_price')

编辑:根据@ ivan的回答和评论修复bug。