【问题标题】:Order a Django queryset in ascending order but with 0-valued items at the end以升序排列 Django 查询集,但最后有 0 值项
【发布时间】: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") 吗?

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


【解决方案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()
      

      【讨论】:

        猜你喜欢
        • 2012-07-30
        • 1970-01-01
        • 2013-09-26
        • 2011-03-08
        • 2013-04-08
        • 2018-11-19
        • 2017-09-09
        • 1970-01-01
        • 2010-10-30
        相关资源
        最近更新 更多