以升序排列 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 值项的主要内容,如果未能解决你的问题,请参考以下文章