在 Django 中获取查询集中的对象计数

如何为数据库中的对象计数添加字段:

class Item(models.Model):
name = models.CharField()


class Contest(models.Model);
name = models.CharField()


class Votes(models.Model):
user = models.ForeignKey(User)
item = models.ForeignKey(Item)
contest = models.ForeignKey(Contest)
comment = models.TextField()

在我的视图中,我使用下面的查询来查找比赛的投票

current_vote = Item.objects.filter(votes__contest=contestA)

这将返回一个查询集,其中包含所有单独的投票,但是我想获得每个项目的计数投票,有人知道我如何做到这一点吗?谢谢

195880 次浏览

To get the number of votes for a specific item, you would use:

vote_count = Item.objects.filter(votes__contest=contestA).count()

If you wanted a break down of the distribution of votes in a particular contest, I would do something like the following:

contest = Contest.objects.get(pk=contest_id)
votes   = contest.votes_set.select_related()


vote_counts = {}


for vote in votes:
if not vote_counts.has_key(vote.item.id):
vote_counts[vote.item.id] = {
'item': vote.item,
'count': 0
}


vote_counts[vote.item.id]['count'] += 1

This will create dictionary that maps items to number of votes. Not the only way to do this, but it's pretty light on database hits, so will run pretty quickly.

Another way of doing this would be using Aggregation. You should be able to achieve a similar result using a single query. Such as this:

from django.db.models import Count


Item.objects.values("contest").annotate(Count("id"))

I did not test this specific query, but this should output a count of the items for each value in contests as a dictionary.

Use related name to count votes for a specific contest

class Item(models.Model):
name = models.CharField()


class Contest(models.Model);
name = models.CharField()


class Votes(models.Model):
user = models.ForeignKey(User)
item = models.ForeignKey(Item)
contest = models.ForeignKey(Contest, related_name="contest_votes")
comment = models.TextField()


>>> comments = Contest.objects.get(id=contest_id).contest_votes.count()

You can use len() to get the count of contestA's votes:

current_vote = len(Item.objects.filter(votes__contest=contestA))