Как ограничить количество записей в сериализаторе

Здравствуйте, как ограничить количество результатов с помощью сериализатора?

Вкратце, есть таблица комментариев, которая может содержать различные типы постов.

class CourseComment(models.Model):
    user = models.ForeignKey(User, on_delete=models.PROTECT)
    content = models.TextField()
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

и вот соответствующая таблица

class CourseMessage(models.Model):
    course_id = models.ForeignKey(Course, on_delete=models.PROTECT)
    author_id = models.ForeignKey(User, on_delete=models.PROTECT)
    text = models.TextField()   # RAW Format must exclude specials chars before publish
    is_pinned = models.BooleanField(default=False)
    comments = GenericRelation('CourseComment')
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

Я сделал сериализатор в соответствии с документацией https://www.django-rest-framework.org/api-guide/relations/

class CourseMessages(serializers.ModelSerializer):
    user = Author(source='authorid', read_only=True)
    files = MessageFiles(source='coursemessageattachedfile_set', many=True)      
    message_comments = MessageComments(source='comments', many=True, read_only=True)

    class Meta:
        model = CourseMessage
        fields = ['text', 'updated_at', 'user', 'files', 'message_comments']


class MessageComments(serializers.RelatedField):
    def to_representation(self, value):
        ct = ContentType.objects.get_for_model(value)
        serializer = Comments(value, read_only=True, source='last_comments')
        return serializer.data


class Comments(serializers.ModelSerializer):
    author = Author(source='user', read_only=True)

    class Meta:
        model = CourseComment
        fields = ['content', 'author']

Все работает хорошо, но хотелось бы видеть первые 3 комментария. Может кто-то сталкивался с такой проблемой или может подсказать как лучше сделать. Я получаю эти данные для детальной страницы RetrieveAPIView. Первые три комментария нужны для отображения на передней панели.

требования Django==3.2.5 djangorestframework==3.12.4

Заранее спасибо :)

Я думаю, что вы ничего не получите, указав сериализатору возвращать подмножество набора результатов. Я думаю, что лучшим способом является фильтрация подмножества при составлении запроса или фильтрация массива после сериализации:

result_set = CourseComment.objects.all()[:3] # model
three_first = Comment(result_set, many=True).data # serializer

или

result_set = CourseComment.objects.all() # model
three_first = Comment(result_set, many=True).data[:3] # serializer

Или вы можете даже отправить подмножество набора результатов в сериализатор:

result_set = CourseComment.objects.all() # model
three_first = Comment(result_set[:3], many=True).data # serializer

Если вы используете набор запросов как:

class ViewName(generics.RetriveAPIView):
    permission_classes = [IsAuthenticated]
    serializer_class = Comments
    queryset = CourseComment.objects.all()

тогда вы можете использовать внутри вашей функции списка:

def list(self, request, *args, **kwargs):
    serializer = Comments(self.get_queryset().order_by('-id')[:3], many = True)

Надеемся, что это сработает для вас.

Я думаю, что вы ищете SerializerMethodField()

Итак, ваш код должен выглядеть следующим образом:

class CourseMessages(serializers.ModelSerializer):
    user = Author(source='authorid', read_only=True)
    files = MessageFiles(source='coursemessageattachedfile_set', many=True)      
    message_comments = serializers.SerializerMethodField()

    def get_message_comments(self, obj):
        message_comments = Comments.objects.all()[:3]
        return MessageComments(message_comments, source='comments', many=True, read_only=True).data

    class Meta:
        model = CourseMessage
        fields = ['text', 'updated_at', 'user', 'files', 'message_comments']
Вернуться на верх