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