Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting a count of objects in a queryset in django

How can I add a field for the count of objects in a database. I have the following models:

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() 

To find the votes for contestA I am using the following query in my view

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

This returns a queryset with all of the votes individually but I want to get the count votes for each item, anyone know how I can do that? thanks

like image 200
thesteve Avatar asked Mar 26 '11 02:03

thesteve


People also ask

How does Django count QuerySet?

A QuerySet is evaluated when you call len() on it. This, as you might expect, returns the length of the result list. Note: If you only need to determine the number of records in the set (and don't need the actual objects), it's much more efficient to handle a count at the database level using SQL's SELECT COUNT(*) .

How do I find the length of a QuerySet?

If the QuerySet only exists to count the amount of rows, use count(). If the QuerySet is used elsewhere, i.e. in a loop, use len() or |length. Using count() here would issue another SELECT-query to count the rows, while len() simply counts the amount of cached results in the QuerySet.


2 Answers

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.

like image 109
Gary Chambers Avatar answered Nov 08 '22 23:11

Gary Chambers


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:

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.

like image 36
salomonvh Avatar answered Nov 08 '22 22:11

salomonvh