Search code examples
pythondjangodjango-modelsormmany-to-many

How to get count of objects in a ManyToManyField with 'self' / its own model in django?


I'm trying to implement a network where users can follow each other in django like so:

> class User(AbstractUser):
>     followings = models.ManyToManyField('self', related_name='followers', symmetrical=False)

So the followings field is going to contain all the users a user is following, and I would also like to be able to access all of the user's followers, thus the related_name.

My question is, if I have a user's username, how can I make a query to retrieve that user object, with the annotation of its number of followings and number of followers? Here's what I've tried:

data = User.objects.annotate(number_of_followers=Count('followers'), number_of_followings=Count('followings')).get(username=user)

It seems alright to me, but somehow it's showing values that doesn't match the real numbers as in the actual database, as I've checked using the django admin app.


Solution

  • It turns out that combining multiple aggregations (in my case, Count) using annotate will yield wrong results, as recorded in the documentation:

    https://docs.djangoproject.com/en/3.1/topics/db/aggregation/#combining-multiple-aggregations

    Luckily, I can use the distinct parameter because I'm using Count. Here's the working line:

    data = User.objects.annotate(number_of_followers=Count('followers', distinct=True), number_of_followings=Count('followings', distinct=True)).get(username=user)