So I have a social media app, where users can like the posts of other users. Now I want to fetch the top 20 users who have received the most number of likes. I am pretty much confused how to query my Likes Model
My LIKES MODEL
JavaScript
x
5
1
class PostLike(models.Model):
2
user_who_liked = models.ForeignKey(User, on_delete=models.CASCADE)
3
post_liked = models.ForeignKey(Post, on_delete=models.CASCADE)
4
liked_on = models.DateTimeField(default=timezone.now)
5
SIMPLIFIED POST MODEL
JavaScript
1
12
12
1
class Post(models.Model):
2
id = models.AutoField(primary_key=True)
3
user = models.ForeignKey(User, on_delete=models.CASCADE)
4
caption = models.TextField()
5
date = models.DateTimeField(default=timezone.now)
6
likes = models.ManyToManyField(
7
User, blank=True, through=PostLike)
8
image = models.TextField()
9
10
class Meta:
11
ordering = ['-id']
12
SIMPLIFIED USER MODEL
JavaScript
1
13
13
1
class User(AbstractBaseUser, PermissionsMixin):
2
email = models.EmailField(unique=True)
3
user_name = models.CharField(max_length=100, unique=True)
4
date = models.DateTimeField(default=timezone.now)
5
profile_picture = models.TextField(
6
default="https://www.kindpng.com/picc/m/24-248253_user-profile-default-image-png-clipart-png-download.png")
7
bio = models.CharField(max_length=200, default="")
8
objects = CustomManger()
9
10
def __str__(self):
11
return self.user_name
12
13
** My View **
JavaScript
1
6
1
@api_view(["GET"])
2
@permission_classes([IsAuthenticated])
3
def leaderboard(request):
4
# I dont know how to query the PostLike model now to get the most liked users
5
pass
6
Advertisement
Answer
First I changed the user
attribute in your Post
model, I added related_name
because otherwise the related names were clashing. This is the definition I used, otherwise your models are unchanged.
JavaScript
1
2
1
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='author')
2
I.e. the posts by a user are accessible on User
via the author
attribute.
The following query gives you the top 20 users by number of likes they received:
JavaScript
1
2
1
User.objects.annotate(num_likes=Count('author__likes')).order_by('-num_likes')[:20]
2
Explanation:
- Query
User
model and - annotate each user by doing a count:
author
leads to the posts by the userlikes
follows toPostLike
and counts all likes which are associated with a post by the user
- then order by number of likes descending,
- and limit the number of retrieved objects to 20.