In Django Rest Framework, how to limit number foreign key objects being serialized
U

3

8

I'm serialzing a Product model and its comments. Here's my simple code:

class ProductSerializer(serializers.HyperlinkedModelSerializer):
    comment_set = CommentSerializer(many=True, read_only=True)
    class Meta:
        model = Product
        fields = [
            'title',
            'comment_set'
        ]


class CommentSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Comment
        fields = [
            'text',
        ]


class Comment(models.Model):
    product = models.ForeignKey(Product, null=True, blank=True, db_index=True)


class Product(models.Model):
    title = models.CharField(max_length=50)
    ...

Problem: If the product has many comments. For example, 500 comments. All 500 of them got serialized.

How to limit the result to a number of my own choosing, like 100 comments?

I've done some research before posting this but only found questions about filtering.

Thank you.

Upstanding answered 10/7, 2016 at 6:39 Comment(1)
django-rest-framework.org/api-guide/paginationStauffer
P
2

You'll want to work on the CommentSerializer's queryset to control which ones you keep.

You'll be able to do that by overriding get_queryset. For example, to filter them against the current user. Note that I took this example because it highlights how to use the request's context to filter against:

class CommentSerializer(serializers.HyperlinkedModelSerializer):
    def get_queryset(self):
        user = self.context['request'].user
        queryset = Comment.objects.filter(user=user)
        return queryset

    class Meta:
        model = Comment
        fields = [
            'text',
        ]
Parimutuel answered 10/7, 2016 at 10:45 Comment(2)
Thanks. Works perfectly and thanks for pointing out the request context. Also thank you for other answers too although I haven't tested your solutions yet. But they should also work.Upstanding
As of 2020, this code won't let you limit the query resultsCaracul
M
10

Define a new method on the Product model that returns a query set with a limited number of comments.

Then pass that method as the source of the CommentSerializer inside your ProductSerializer.

class Product(models.Model):
    title = models.CharField(max_length=50)


    def less_comments(self):
        return Comment.objects.all().filter(product=self).order_by("-id")[:100]

Then in the ProductSerializer:

class ProductSerializer(serializers.HyperlinkedModelSerializer):
    comment_set = CommentSerializer(many=True, read_only=True, source="less_comments")

PS: Wrote the codes from memory, didn't test them. But should work.

Monkhmer answered 10/7, 2016 at 6:42 Comment(0)
C
5

You can write custom ListSerializer and put in CommentSerializer, then create custom field in ProductSerializer, wich source based on default related name:

class LimitedListSerializer(serializers.ListSerializer):

    def to_representation(self, data):
        data = data.all()[:100]
        return super(FilteredListSerializer, self).to_representation(data)

class CommentSerializer(serializers.HyperlinkedModelSerializer):

    class Meta:
            list_serializer_class = LimitedListSerializer
            model = Comment
            fields = [
                'text',]

class Product(serializers.HyperlinkedModelSerializer):
    related_comments = CommentSerializer(many=True, read_only=True, source='comment_set')

when you pass many=True, list serrializer will be called.

Comical answered 10/7, 2016 at 7:9 Comment(0)
P
2

You'll want to work on the CommentSerializer's queryset to control which ones you keep.

You'll be able to do that by overriding get_queryset. For example, to filter them against the current user. Note that I took this example because it highlights how to use the request's context to filter against:

class CommentSerializer(serializers.HyperlinkedModelSerializer):
    def get_queryset(self):
        user = self.context['request'].user
        queryset = Comment.objects.filter(user=user)
        return queryset

    class Meta:
        model = Comment
        fields = [
            'text',
        ]
Parimutuel answered 10/7, 2016 at 10:45 Comment(2)
Thanks. Works perfectly and thanks for pointing out the request context. Also thank you for other answers too although I haven't tested your solutions yet. But they should also work.Upstanding
As of 2020, this code won't let you limit the query resultsCaracul

© 2022 - 2024 — McMap. All rights reserved.