Yes, you can use double underscores (__
) to look through a relation:
from django.db.models import Count
Domain.objects.annotate(
num_posts=Count('topics__posts')
)
if you combine this with counting the number of Topic
s, you will need to add distinct=True
to the Count
of the Topic
s, since this will make two JOIN
s, and the JOIN
on Post
s will act as a "multiplier":
from django.db.models import Count
Domain.objects.annotate(
num_posts=Count('topics__posts'),
num_topics=Count('topics', distinct=True)
)
This will result in a query like:
SELECT domain.*
COUNT(post.id) AS num_posts
COUNT(DISTINCT topic.id) AS num_topics
FROM domain
LEFT OUTER JOIN topic ON topic.domain_id = domain.id
LEFT OUTER JOIN post ON post.topic_id = topic.id
GROUP BY domain.id
If you would have omitted the distinct=True
, the same topic would be counted multiple times (exactly the same number of times as the number of posts related to that topic), and thus num_topics
should then be the same as num_posts
. By using DISTINCT
we count the number of unique topics in each group.