Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Count number of records by date in Django

I have a model similar to the following:

class Review(models.Model):
    venue = models.ForeignKey(Venue, db_index=True)
    review = models.TextField()  
    datetime_created = models.DateTimeField(default=datetime.now)

I'd like to query the database to get the total number of reviews for a venue grouped by day. The MySQL query would be:

SELECT DATE(datetime_created), count(id) 
FROM REVIEW 
WHERE venue_id = 2
GROUP BY DATE(datetime_created);

What is the best way to accomplish this in Django? I could just use

Review.objects.filter(venue__pk=2)

and parse the results in the view, but that doesn't seem right to me.

like image 258
doza Avatar asked Feb 17 '10 03:02

doza


3 Answers

This should work (using the same MySQL specific function you used):

Review.objects.filter(venue__pk=2)
    .extra({'date_created' : "date(datetime_created)"})
    .values('date_created')
    .annotate(created_count=Count('id'))
like image 63
ara818 Avatar answered Nov 08 '22 08:11

ara818


Now that Extra() is being depreciated a more appropriate answer would use Trunc such as this accepted answer

Now the OP's question would be answered as follows

from django.db.models.functions import TruncDay

Review.objects.all()
    .annotate(date=TruncDay('datetime_created'))
    .values("date")
    .annotate(created_count=Count('id'))
    .order_by("-date")
like image 37
Anthony Manning-Franklin Avatar answered Nov 08 '22 09:11

Anthony Manning-Franklin


Just for completeness, since extra() is aimed for deprecation, one could use this approach:

from django.db.models.expressions import DateTime

Review.objects.all().\
    annotate(month=DateTime("timestamp", "month", pytz.timezone("Etc/UTC"))).\
    values("month").\
    annotate(created_count=Count('id')).\
    order_by("-month")

It worked for me in django 1.8, both in sqlite and MySql databases.

like image 17
avikam Avatar answered Nov 08 '22 09:11

avikam