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

avatar
hardym3n
8 августа 2021 в 20:19
288
3
1

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

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

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. Первые три комментария обязательны для отображения на лицевой стороне.

требования Джанго==3.2.5 djangorestframework==3.12.4

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

Источник

Ответы (3)

avatar
em294
9 августа 2021 в 19:36
1

Я думаю, что вы ищете 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']
avatar
user15195370
9 августа 2021 в 11:43
0

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

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)

Надеюсь, это сработает для вас.

avatar
HuLu ViCa
8 августа 2021 в 21:41
2

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

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