Ilyes GHOMRANI
Ilyes GHOMRANI

Reputation: 122

List of Users ordered by the rank of their Posts reviews

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

Answers (2)

Ilyes GHOMRANI
Ilyes GHOMRANI

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

Navid Zarepak
Navid Zarepak

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

Related Questions