Reputation: 122
I want to make an API End Point
so the user can get a list of the users in his city ordered by their post reviews
I have defined a method in the post model to calculate the total review (up vote and down vote), I'm imagining that the solution can be realized in the following path but I'm not entirely sure groupBy post_owner
in the post and orderBy sum(count_reactions())
, but I don't know how to do it in django
Post Model
class Post(models.Model):
title = models.TextField(max_length=255, default='Title')
post_owner = models.ForeignKey(MyUser, on_delete=models.CASCADE)
description = models.TextField(max_length=255)
city = models.ForeignKey(City, related_name='location', on_delete=models.CASCADE)
longitude = models.CharField(max_length=255)
image = models.CharField(max_length=255,
default='https://www.eltis.org/sites/default/files/styles/web_quality/public/default_images/photo_default_2.png')
latitude = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
def count_reactions(self):
likes_count = Reaction.objects.filter(post=self.id, is_like=True).count()
dislikes_count = Reaction.objects.filter(post=self.id, is_like=False).count()
return likes_count - dislikes_count
def owner(self):
return self.post_owner
MyUser Model
class MyUser(AbstractUser):
phone_number = models.BigIntegerField(blank=False, unique=True)
city = models.ForeignKey(City, related_name='city', on_delete=models.CASCADE)
address = models.CharField(max_length=255)
def owner(self):
return self
Reaction Model
class Reaction(models.Model):
reaction_owner = models.ForeignKey(MyUser, on_delete=models.CASCADE)
post = models.ForeignKey(Post, related_name='reactions', on_delete=models.CASCADE)
is_like = models.BooleanField(null=False)
def owner(self):
return self.reaction_owner
The expected result is to get the ordered list of the users by their posts reviews but only the users in the same city (city field in MyUser
model)
Upvotes: 0
Views: 109
Reputation: 122
The answer is Navid's answer but completing it with excluding the users with rank equal to zero and include also the limit
# Filter for the city you want
users = MyUser.objects.filter(city=your_city_obj)
# Then doing the calculations
users = users.annotate(rank_point=(Count('post__reactions', filter=Q(post__reactions__is_like=True)) - (Count('post__reactions', filter=Q(post__reactions__is_like=False))))).filter(rank_point__gt=0)
# And finaly, order the results
users = users.order_by('-rank_point')[:LIMIT]
Upvotes: 1
Reputation: 4208
You can put it all into one query.
Depending on where your Reaction
naming the query should look something like this:
# Filter for the city you want
users = MyUser.objects.filter(city=your_city_obj)
# Then doing the calculations
users = users.annotate(rank_point=(Count('post__reactions', filter=Q(post__reactions__is_like=True)) - (Count('post__reactions', filter=Q(post__reactions__is_like=False)))))
# And finaly, order the results
users = users.order_by('-rank_point')
Upvotes: 1