I have a task where I need to get stats and feedback by moderator ID. The 'stats' field is general, the 'feedback' field is a list of feedbacks. Can I make pagination for 'feedback' field? Of course I can make different endpoints for stats and feedback, but I'm not allowed to do this.
// GET /api/moderators/:id/feedback
{
"stats": [
{
"name": "123",
"value": -10
}
],
"feedback": [
{
"id": 1,
"createdBy": "FN LN",
"createdAt": "DT",
"comment": "",
"score": 5,
"categories": [
{
"name": "123",
"status": "POSITIVE/NEGETIVE/UNSET"
}
],
"webinarID": 123456
},
{
...
}
]
}
views.py
class TeacherFeedbackViewSet(ViewSet):
permission_classes = [IsAuthenticated, TeacherFeedbackPerm]
renderer_classes = [CamelCaseJSONRenderer]
@base_view
def list(self, request, pk):
moderator = get_object_or_404(Moderator, pk=pk)
serializer = ModeratorFeedback(moderator)
return Response(serializer.data)
serializers.py
class TeacherFeedbackSerializerDetail(ModelSerializer):
created_at = DateTimeField(source='datetime_filled')
created_by = SerializerMethodField(method_name='get_created_by')
categories = SerializerMethodField(method_name='get_categories')
webinar_id = IntegerField(source='webinar.id')
moderator_id = IntegerField(source='moderator.id')
class Meta:
model = TeacherFeedback
fields = ['id', 'created_by', 'created_at', 'categories', 'score', 'comment', 'moderator_id', 'webinar_id']
def get_categories(self, feedback: TeacherFeedback):
data = []
category_names = list(FeedbackCategory.objects.all().values_list('name', flat=True))
for category in feedback.category.all():
z = TeacherFeedbackCategory.objects.get(category=category, feedback=feedback)
data.append({"name": z.category.name, "status": z.status})
unset = list(map(lambda x: {"name": x, "status": "unset"},
list(set(category_names) - set([i["name"] for i in data]))))
return sorted(data unset, key=lambda x: x["status"])
def get_created_by(self, feedback: TeacherFeedback):
return str(feedback.created_by.teacher)
class ModeratorFeedback(serializers.ModelSerializer):
stats = serializers.SerializerMethodField(method_name='get_stats_list')
feedback = TeacherFeedbackSerializerDetail(many=True, source='actual_feedbacks')
class Meta:
model = Moderator
fields = ['stats', 'feedback']
def get_stats_list(self, moderator: Moderator):
data = {}
for feedback in moderator.actual_feedbacks:
for category in feedback.category.all():
category_detail = TeacherFeedbackCategory.objects.get(feedback=feedback, category=category)
if category.name not in data:
data[category.name] = [category_detail.status]
else:
data[category.name].append(category_detail.status)
stats = []
for k, statuses in data.items():
weight = 100/len(statuses)
current_value = 0
for status in statuses:
if status == 'positive':
current_value = weight
else:
current_value -= weight
stats.append({"name": k, "value": float("{0:.2f}".format(current_value))})
return stats
CodePudding user response:
In order to realize the pagination here, you need to make serializer for stats
and feedback
data respectively.
First you can define the ModeratorStats
serializer.
class ModeratorStats(serializers.ModelSerializer):
stats = serializers.SerializerMethodField(method_name='get_stats_list')
class Meta:
model = Moderator
fields = ['stats']
def get_stats_list(self, moderator: Moderator):
...
And TeacherFeedbackSerializerDetail
serializer is for the feedback.
Now in view,
from django.core.paginator import Paginator
from rest_framework.response import Response
class TeacherFeedbackViewSet(ViewSet):
...
@base_view
def list(self, request, pk):
moderator = get_object_or_404(Moderator, pk=pk)
# first get page and size param
page = int(request.GET.get('page', "1"))
size = int(request.GET.get('size', "10"))
# here I assumed the foreign key field name is `moderator`
query_set = TeacherFeedback.objects.filter(moderator__id = pk)
paginator = Paginator(query_set.order_by('id'), size)
feedbacks = paginator.page(page)
stats_data = ModeratorStats(moderator).data
feedbacks = TeacherFeedbackSerializerDetail(feedbacks, many=True).data
return Response({"stats": stats_data, "feedback": feedbacks})
And in frontend, you need to upload pagination params like ...?page=1&size=10
.