Django 对选择的聚合

Django aggregation over choices

我有以下型号:

class VotingRound(models.Model):
     pass # here are some unimportant fields

class Vote(models.Model):
     voting_round = models.ForeignKey(VotingRound)
     vote = models.CharField(choices=...)

现在我有了 VotingRound 的实例,我想知道每个值代表了多少次。这很容易通过 collections.Counter:

完成
>>> Counter(voting_round_instance.vote_set.values_list('vote', flat=True))
Counter({u'decline': 8, u'neutral': 5, u'approve': 4})

现在我想知道是否有办法使用 Django 聚合技术来做到这一点....

我找到了 this module,但在使用它之前我想知道是否有本地方法可以做到这一点。

是的,你可以!

from django.db.models import Count
voting_round_instance.vote_set.values('vote') \
    .annotate(count=Count('vote')).distinct()

编辑: 使用 order_by()

您可能还需要确保默认排序不会弄乱您的聚合。使用相关对象管理器时尤其如此。

https://docs.djangoproject.com/en/1.8/topics/db/aggregation/#interaction-with-default-ordering-or-order-by

Fields that are mentioned in the order_by() part of a queryset (or which are used in the default ordering on a model) are used when selecting the output data, even if they are not otherwise specified in the values() call. These extra fields are used to group “like” results together and they can make otherwise identical result rows appear to be separate. This shows up, particularly, when counting things.

from django.db.models import Count
voting_round_instance.vote_set.values('vote') \
    .annotate(count=Count('vote')) \
    .distinct().order_by()