'How to add field to Django queryset
I'm learning DRF and trying to make website, where users can leave reviews for some products and also rate (like or dislike) this reviews. So now I'm stuck in like system. For example I have these models:
class Review(models.Model):
author = models.ForeignKey(User)
text = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
class Reaction(models.Model):
author = models.ForeignKey(User)
review = models.ForeignKey(Review, related_name='reactions')
like = models.BooleanField() # True = like, False = dislike
And I want to show list of posts with like and dislike counters and also somehow mark that logged user already liked or disliked a post. I made view to list posts with counters, but don't know how to include information about post was rated by user.
class ListReviews(generics.ListAPIView):
serializer_class = ProductReviewSerializer
def get_queryset(self):
product_slug = self.kwargs['product_slug']
queryset = Review.objects.filter(product__slug=product_slug).annotate(
likes_count=Count('reactions', filter=Q(reactions__like=True)),
dislikes_count=Count('reactions', filter=Q(reactions__like=False)),
user_reaction=...
)
return queryset
Is it possible at all? Or it's better to just make another endpoint to get user reactions for current page?
Solution 1:[1]
This can be done using a Subquery that selects Reviews filtered by the current user and use that as an annotation
# You'll need these imports
from django.db.models import Q, Count, OuterRef, Subquery
def get_queryset(self):
product_slug = self.kwargs['product_slug']
user_reactions = Reaction.objects.filter(review=OuterRef('pk'), author=self.request.user)
queryset = Review.objects.filter(product__slug=product_slug).annotate(
likes_count=Count('reactions', filter=Q(reactions__like=True)),
dislikes_count=Count('reactions', filter=Q(reactions__like=False)),
user_reaction=Subquery(user_reactions.values('like')[:1])
)
return queryset
The user_reaction annotation will then be True, False or None when the user liked a review, disliked a review or hasn't reacted respectively
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Iain Shelvington |
