【问题标题】:Django Aggregation of values querysetDjango 聚合值查询集
【发布时间】:2013-02-28 14:12:38
【问题描述】:

我有一个名为 data 的 ValuesQuerySet。

我正在尝试获取每个对象的所有类型的摘要计数

data.values('type') 产生这个输出:

[{'type': u'internal'}, {'type': u'internal'}, {'type': u'external'}, {'type': u'external'}]

我想得到这样的细分(可以有更多的选择,而不仅仅是“内部”和“外部”。这可能是多达 20 种不同的类型:

internal: 2
external: 2

我正在尝试这个,但它只是返回一个空字典...

data.values('type').aggregate(Count('type'))

Annotate 也会产生不理想的结果:

data.values('type').annotate(Count('type'))


[{'type': u'internal', 'type_count': 1}, {'type': u'internal', 'type_count': 1}, {'type': u'external', 'type_count': 1}, {'type': u'external', 'type_count': 1}]

模型.py

class Purchase(models.Model):    

    type = models.ForeignKey(Types)

【问题讨论】:

  • data是什么类型,data.values('type')是什么类型?
  • 它是一个 ValuesQuerySet

标签: django django-aggregation


【解决方案1】:
 lists = ModelName.objects.values('type').annotate(count=Count('type'))

在html中:

 {% for list in lists %}
     {{list.type}} - {{list.count}}<br/>
 {% endfor %}

测试:

 {{lists}}
 //don't use forloop yet. This will tests if the above query produce data or it is empty

更新:

def view_name(request):
    lists = ModelName.objects.values_list('type', flat=True).distinct()
    types = []
    for list in lists:
        type_count = ModelName.objects.filter(type=list.type).count()
        types.append({'type': list.type, 'count': type_count})

    return render(request, 'page.html', {
            'types': types,
    })

{% for type in types %}
    {{type.type}} - {{type.count}}
{% endfor %}

【讨论】:

  • 那仍然为我返回一个空字典。我在这个模型中有近 50 万个对象,但该查询没有产生任何结果
  • @Austin 尝试将聚合更改为注释。之后在像这样 {{lists}} 的模板测试中,不要使用 forloop。这是为了测试,以便我们知道是否有查询
  • 我确实从使用注释中得到了一些想要的结果。 ValuesQuerySet 与 QuerySet 相比是否存在问题?我想尽量避免另一个数据库调用,因为我的“数据”变量来自使用使用过滤器和排除的查询。然后我从那里获取特定字段的 values() 。我想我只是想了解为什么我的原始代码不起作用。
  • 我在原始帖子中添加了注释并显示了它的结果。不知道为什么会这样显示
  • 因为查询只过滤一个模型。如果类型在另一个模型中,那将很容易。这就是我要求您提供型号代码的原因
【解决方案2】:

它们有几种方法,假设您想要字典中的结果,简单的方法是:

results = { 'internal': data.filter( value = 'internal'  ).count(),
            'external': data.filter( value = 'external'  ).count() }

对于少数查询集,您可以使用 itertools,这会将工作从数据库层转换到 django 层。这意味着它只是针对小查询集的解决方案。

from itertools import groupby
results = groupby(data.all(), lambda x: x.type)

【讨论】:

  • 我应该提到可以有两个以上的选择。除“内部”和“外部”外,最多 20 个
猜你喜欢
  • 1970-01-01
  • 2019-12-04
  • 2014-02-23
  • 2012-04-01
  • 1970-01-01
  • 2012-05-19
  • 1970-01-01
  • 2012-04-14
  • 1970-01-01
相关资源
最近更新 更多