Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: annotate Count with filter

I have "post" objects and a "post like" object with how many likes a post has received by which user:

class Post(models.Model):
    text     = models.CharField(max_length=500, default ='')
    user     = models.ForeignKey(User)

class PostLike(models.Model):
    user    = models.ForeignKey(User)
    post    = models.ForeignKey(Post)

I can select how many likes a post has received like this:

Post.objects.all().annotate(likes=Count('postlike'))

This roughly translates to:

SELECT p.*,
       Count(l.id) AS likes
    FROM post p, postlike l
    WHERE p.id = l.post_id
    GROUP BY (p.id)

It works. Now, how I can filter the Count aggregation by the current user? I'd like to retrieve not all the likes of the post, but all the likes by the logged user. The resulting SQL should be like:

SELECT p.*,
    (SELECT COUNT(*) FROM postlike WHERE postlike.user_id = 1 AND postlike.post_id = p.id) AS likes
FROM post p, postlike l
WHERE p.id = l.post_id
GROUP BY (p.id)
like image 688
pistacchio Avatar asked May 16 '26 16:05

pistacchio


1 Answers

Do you know that Count has a filter argument?

Post.objects.annotate(
    likes=Count('postlike', filter=Q(postlike__user=logged_in_user))
)
like image 189
Krzysztof Szularz Avatar answered May 19 '26 05:05

Krzysztof Szularz