I have Reviews & Ratings
serializer. I want to show the total count of reviews in response. The current implementation I am getting review count but it shows on all review response like below:
[
{
"review_count": 2,
"user": "don sebastian",
"rating": 3.9,
"review": "Rating for pendant 1 by Don",
"created_at": "2022-11-27",
"updated_at": "2022-11-27"
},
{
"review_count": 2,
"user": "Jackson Patrick Gomez",
"rating": 4.5,
"review": "cool review Pendant 1",
"created_at": "2022-11-27",
"updated_at": "2022-11-29"
}
]
What I want to get is like this review_count
seperatley
[
"review_count": 2,
{
"user": "don sebastian",
"rating": 3.9,
"review": "Rating for pendant 1 by Don",
"created_at": "2022-11-27",
"updated_at": "2022-11-27"
},
{
"user": "Jackson Patrick Gomez",
"rating": 4.5,
"review": "cool review Pendant 1",
"created_at": "2022-11-27",
"updated_at": "2022-11-29"
}
]
#Serializer.py
class ReviewSerializer(ModelSerializer):
user = SerializerMethodField()
review_count = SerializerMethodField()
class Meta:
model = ReviewRatings
fields = ["review_count", "user", "rating", "review", "created_at", "updated_at"]
def get_user(self, obj):
return f"{obj.user.first_name} {obj.user.last_name}"
def get_review_count(self, obj):
#Views.py
class ShowReviews(APIView):
def get(self, request, *args, **kwargs):
product_slug = self.kwargs['product_slug']
rating = request.GET.get('rating')
reviews = ReviewRatings.objects.filter(product__slug=product_slug)
review_count = reviews.count()
if rating == 'lowest':
reviews = reviews.order_by('rating')
elif rating == 'highest':
reviews = reviews.order_by('-rating')
if not reviews:
return Response({"error": "No reviews for this product yet"}, status=404)
serializer = ReviewSerializer(reviews, many=True, context={"count":review_count})
return Response(serializer.data, status=status.HTTP_200_OK)
#Edited Views.py
class ShowReviews(APIView):
def get(self, request, *args, **kwargs):
product_slug = self.kwargs['product_slug']
rating = request.GET.get('rating')
reviews = ReviewRatings.objects.filter(product__slug=product_slug)
review_count = reviews.count()
if rating == 'lowest':
reviews = reviews.order_by('rating')
elif rating == 'highest':
reviews = reviews.order_by('-rating')
if not reviews:
return Response({"error": "No reviews for this product yet"}, status=404)
serializer = ReviewSerializer(reviews, many=True)
dict_copy = serializer.data.copy()
dict_copy[0]={"review_count": review_count}
return Response(dict_copy, status=status.HTTP_200_OK)
CodePudding user response:
The easiest way I would assume is to edit your endpoint response directly.
Assuming you approached DRF
as instructed; (this is an easy guideline for you to set up), you are going to remove review_count
from your serializer and approach your get method like so:
def get(self, request, *args, **kwargs):
..........
serializer = ReviewSerializer(reviews, many=True)
dict_copy = serializer.data.copy()
dict_copy[0]=str(Review.objects.all().count()) # or wherever that count comes from
return Response(dict_copy, status=status.HTTP_200_OK)
This way you are making a copy of the serializer and then appending your value there. Since serializer.data
returns an array with a dict inside in order to access that point then you will do dict_copy[0]
. Otherwise if you want to have access to it as a key
-value
pair you can assign it as
dict_copy[0]={"review_count": str(Review.objects.all().count())}
and your result will be something like this:
[
{
"review_count": "4"
},
{
"user": "don sebastian",
"rating": 3.9,
"review": "Rating for pendant 1 by Don",
"created_at": "2022-11-27",
"updated_at": "2022-11-27"
},
Lastly you can try directly editing your response and adding there a key-pair value but I assume it will do you no good as this is outside of your serializer:
x = Review.objects.all().count()
return Response(( {"review_count":str(x)}, serializer.data), status=status.HTTP_200_OK)
[
{
"review_count": "4"
},
[
{
"user": "don sebastian",
"rating": 3.9,
"review": "Rating for pendant 1 by Don",
"created_at": "2022-11-27",
"updated_at": "2022-11-27"
},
....
]