This is my serializer and my problem is with the average_rating field. It's repeated in all the instances
class ReviewSerializer(serializers.ModelSerializer):
average_rating = serializers.SerializerMethodField(read_only=True)
reviewer = serializers.SerializerMethodField(read_only=True)
book = serializers.SlugRelatedField(slug_field='title', read_only=True)
def get_average_rating(self, review):
book_id = self.context['book_id']
return Review.objects.filter(book_id=book_id).aggregate(average_rating=Avg('rating'))
class Meta:
model = Review
fields = ["id", "book", "reviewer", "description", 'rating', 'average_rating', ]
what I get is this:
[
{
"id": 1,
"book": "Clean Code: A Handbook of Agile Software Craftsmanship",
"reviewer": "user1",
"description": "aaaa",
"rating": 5,
"average_rating": {
"average_rating": 4.5
}
},
{
"id": 2,
"book": "Clean Code: A Handbook of Agile Software Craftsmanship",
"reviewer": "user2",
"description": "bbbb",
"rating": 5,
"average_rating": {
"average_rating": 4.5
}
},
]
but I need this: I don't want average_rating to repeat for all instances and make extra queries. what can I do here?
[
"average_rating": {
"average_rating": 4.5
},
{
"id": 1,
"book": "Clean Code: A Handbook of Agile Software Craftsmanship",
"reviewer": "user1",
"description": "aaaa",
"rating": 5,
},
{
"id": 2,
"book": "Clean Code: A Handbook of Agile Software Craftsmanship",
"reviewer": "user2",
"description": "bbbb",
"rating": 5,
},
]
Since you are using SerializerMethodField
the particular query will run with each object which is not a best practice.
You can run the query once in views and return it with response.
avg = Review.objects.aggregate(average_rating=Avg('rating'))
serializer = ReviewSerializer(query, many=True)
return Response({'average_rating':avg['average_rating'], 'item':serializer.data})