以升序排列 Django 查询集,但最后有 0 值项

Posted

技术标签:

【中文标题】以升序排列 Django 查询集,但最后有 0 值项【英文标题】:Order a Django queryset in ascending order but with 0-valued items at the end 【发布时间】:2016-01-19 00:28:36 【问题描述】:

我是 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。

有什么功能可以实现吗?

【问题讨论】:

请向我们展示您的型号代码。 这是模型类 Product(models.Model): name = models.CharField(max_length=100, blank=True, null=True) price = models.IntegerField('Price', blank=真,空=真) 您能否使用编辑链接为您的问题提供更多详细信息,而不是将其添加为评论。 @wtower 在描述中添加了代码 不会是“-price” => [30, 20, 0] 吗?你是说 order_by("price") 吗? 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

如果您真的想要在数据库级别上做所有事情,您可以按计算值排序。这应该有效:

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。

【讨论】:

【参考方案3】:

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 的回答和评论修复错误。

【讨论】:

当我看到@ivan 的答案时,我删除了这个答案,因为我迟到了类似的答案。然后我注意到这个答案有一个“-1”,我不知道为什么这个答案应该得到一个“-1”,即使它有错误,所以我决定取消删除它。 其实有两个错误:第一,this:BIG_VALUE = 999999999 # or sys.maxint?999999999从哪里来?而sys.maxint 取决于平台,在某些情况下是 64 位,在其他情况下是 32 位等。然后order_by('-my_price') 也是错误的——它按降序排列,而问题要求使其升序,除了0 价商品,应该排在最后。 是的,你是对的。但我认为,当有人回答问题时,只要答案不是毫无意义的,他就不值得投反对票。答案可能不正确,但可以指明方向。【参考方案4】:

你想要实现的是这个 SQL 查询:

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

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

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

【讨论】:

以上是关于以升序排列 Django 查询集,但最后有 0 值项的主要内容,如果未能解决你的问题,请参考以下文章

按日期升序排列的日期栏频率条形图

过滤 Django 查询集以获取 dict 值

2.01 以指定的次序返回查询结果

django模型中的meta选项整理

Django - 按 CharField 值长度过滤查询集

在django模板中按id的顺序显示查询集及其外键