I am currently trying to annotate two different number of likes to a User model in Django.
Here's the code I'm using to return the desired querySet
def get_top_user(self):
return User.objects. \
annotate(guide_like=Count('guidelike')).\
annotate(news_like=Count('newslike')).\
values_list('first_name', 'last_name', 'guide_like','news_like').\
order_by('-guide_like')
However, the querySet returns ["Bob", "Miller", 612072, 612072]. As you can see, Django takes the two annotate values and multiply them together and that's why I'm getting 612072.
Is there a way to call multiple annotate in a single querySet without getting these multiplied values.
EDIT: Also tried to add distinct() at the end of the query or distinct=True in each count but the call simply gets into an infinite loop.
This is how django annotate produce sql code: it's do all necessary joins and then group by over all User fields, aggregating with annotation function(count in your case). So, it joins users with all their guide likes and then with all news likes and then simply counts number of rows produced per user.
If you can, you should use raw querysets, or extra
Queryset method. E.g:
User.objects.all().extra(select={
'guide_likes': 'select count(*) from tbl_guide_likes where user_id=tbl_users.id',
'news_like': 'select count(*) from tbl_news_likes where user_id=tbl_users.id'
}).\
values_list('first_name', 'last_name', 'guide_like','news_like')
For more flexibility you can use select_params
parameter of extra
method for providing names of tables(which you can get through Model._meta
). By the way this is very unconvenient and hackish method.
Sooner or later your logic become more complicated and then you should remove it from python code to sql(stored functions/procedures) and raw queries.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With