Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 267
Kitti Wateesatogkij Avatar asked Jul 10 '16 06:07

Kitti Wateesatogkij


2 Answers

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.

like image 83
masnun Avatar answered Oct 03 '22 17:10

masnun


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.

like image 44
Ivan Semochkin Avatar answered Oct 03 '22 19:10

Ivan Semochkin