提问者:小点点

如何在Django中按组查询?


我查询一个模型:

Members.objects.all()

然后返回:

Eric, Salesman, X-Shop
Freddie, Manager, X2-Shop
Teddy, Salesman, X2-Shop
Sean, Manager, X2-Shop

我想知道向数据库激发group_by查询的最佳Django方法,例如:

Members.objects.all().group_by('designation')

当然,这是行不通的。 我知道我们可以在django/db/models/query.py上做一些小技巧,但我只是很好奇知道如何在不打补丁的情况下做。


共3个答案

匿名用户

如果您打算进行聚合,则可以使用ORM的聚合特性:

from django.db.models import Count
Members.objects.values('designation').annotate(dcount=Count('designation'))

这将导致类似于

SELECT designation, COUNT(designation) AS dcount
FROM members GROUP BY designation

输出的形式为

[{'designation': 'Salesman', 'dcount': 2}, 
 {'designation': 'Manager', 'dcount': 2}]

匿名用户

一个简单的解决方案,但不是正确的方法是使用原始SQL:

results = Members.objects.raw('SELECT * FROM myapp_members GROUP BY designation')

另一种解决方案是使用group_by属性:

query = Members.objects.all().query
query.group_by = ['designation']
results = QuerySet(query=query, model=Members)

现在可以迭代results变量来检索结果。 请注意,group_by没有文档化,可能会在Django的未来版本中进行更改。

然后。。。 为什么要使用group_by? 如果不使用聚合,可以使用order_by来实现类似的结果。

匿名用户

还可以使用regroup模板标记按属性分组。 从文档中:

cities = [
    {'name': 'Mumbai', 'population': '19,000,000', 'country': 'India'},
    {'name': 'Calcutta', 'population': '15,000,000', 'country': 'India'},
    {'name': 'New York', 'population': '20,000,000', 'country': 'USA'},
    {'name': 'Chicago', 'population': '7,000,000', 'country': 'USA'},
    {'name': 'Tokyo', 'population': '33,000,000', 'country': 'Japan'},
]

...

{% regroup cities by country as country_list %}

<ul>
    {% for country in country_list %}
        <li>{{ country.grouper }}
            <ul>
            {% for city in country.list %}
                <li>{{ city.name }}: {{ city.population }}</li>
            {% endfor %}
            </ul>
        </li>
    {% endfor %}
</ul>

看起来是这样的:

  • 印度
      孟买:19,000,000 加尔各答:15,000,000
      纽约:20,000,000 芝加哥:7,000,000
      东京:33,000,000

    我相信它也适用于queryset

    来源:https://docs.djangoproject.com/en/2.1/ref/templates/builtins/#regroup

    编辑:请注意,如果词典列表不是按键排序的,regroup标记将无法正常工作。 它以迭代的方式工作。 因此,在将列表(或查询集)传递给regroup标记之前,按石斑鱼的键对其进行排序。