【问题标题】:Django: Filtering a queryset then countDjango:过滤查询集然后计数
【发布时间】:2017-06-08 09:14:23
【问题描述】:

我正在尝试限制我在页面上执行的查询数量。查询集返回过去 24 小时内创建的对象。然后,我想过滤该查询集以根据字段计算对象。

例子:

cars = self.get_queryset()
volvos_count = cars.filter(brand="Volvo").count()
mercs_count = cars.filter(brand="Merc").count()

随着品牌数量的增加(在此示例中),查询数量随着必须查询的品牌数量线性增长。

如何对汽车进行单个查询,以返回品牌的所有唯一值和查询集中实例数的字典?

结果:

{'volvos': 4, 'mercs': 50, ...}

谢谢!

编辑:

到目前为止,在 cmets 中,它们已经接近但并不完全符合要求。使用values_list('brand', flat=True) 将返回品牌。从那里你可以使用

 from collections import Counter 

返回总数。如果有一种方法可以从单个查询中执行此操作,那就太好了,但也许这是不可能的。

【问题讨论】:

    标签: python django django-queryset django-orm


    【解决方案1】:

    要为每个不同的品牌生成计数,请将valuesannotate 结合使用。

    totals = cars.values('brand').annotate(Count('brand'))
    

    这为您提供了一个查询集,其每个元素都是带有brandbrand__count 的字典。您可以将其直接转换为您想要的格式的字典:

    {item['brand']: item['brand__count'] for item in totals}
    

    【讨论】:

    • 这很接近,似乎一种方法就是 queryset.values_list('brand', flat=True) 然后在结果上使用 Counter 。这将返回我正在寻找的值和计数。
    • 使用 Counter 确实可行 - 但一旦您开始获得大量结果,就会变得非常缓慢。这种工作更适合数据库。
    【解决方案2】:
    SELECT brand, COUNT(*) as total 
    FROM cars 
    GROUP BY brand 
    ORDER BY total DESC
    

    等效:

    cars.objects.all().values('brand').annotate(total=Count('brand')).order_by('total')

    【讨论】:

      猜你喜欢
      • 2017-12-26
      • 1970-01-01
      • 2020-08-22
      • 2019-04-15
      • 2011-09-29
      • 2013-06-11
      相关资源
      最近更新 更多