3

First time asking here, I'll try to sound smart! So, I've got a model called 'Article', and I've populated its 'text' field with 1000+ chars of text. How can I make it so I only send the first 200 chars of the 'text' field when I send an 'Article' serialized object through an endpoint?

views.py

class ArticleScrape(generics.ListAPIView):                                                                                                                                                                          
    queryset = Article.objects.all()                                                                                                                                                                                
    serializer_class = ArticleSerializer                                                                                                                                                                            

    def list(self,request):                                                                                                                                                                           
        serializer = ArticleSerializer(queryset, many=True)                                                                                                                                                         
        return Response(serializer.data) 

serializers.py

class ArticleSerializer(serializers.ModelSerializer):                                                                                                                                                               
    authors = EachAuthorSerializer(many=True,read_only=True)                                                                                                                                                        
    tags = EachTagSerializer(many=True,read_only=True)                                                                                                                                                              
    text = serializers.CharField(max_length=200)                                                                                                                                                                    
    class Meta:                                                                                                                                                                                                     
        model = Article                                                                                                                                                                                             
        exclude=('id',) 

Do I need to perform this operation in the queryset? in the serializer? Do I annotate a field? I've tried many of this with no succes. Thanks in advance for the help!

Rne
  • 53
  • 6

3 Answers3

3

There are different approaches, the first one that I prefer is to add a property to your model and add its field to the serializer:

class Article(models.Modle):
    ...
    @property
    def summary(self):
        return self.text[:200]


class ArticleSerializer(serializers.ModelSerializer):                                                                                                                                                               
    summary = serializers.CharField()                                                                                                                                                        

and for the second approach you can use SerializerMethodField:

class ArticleSerializer(serializers.ModelSerializer):                                                                                                                                                               
    summary = serializers.SerializerMethodField() 

    def get_summary(self, obj):
        return obj.text[:200]
Ehsan Nouri
  • 1,990
  • 11
  • 17
  • That's pretty clean. I ended up doing it using a mix of two other SO answers: [annotating a field](https://stackoverflow.com/questions/31920853/aggregate-and-other-annotated-fields-in-django-rest-framework-serializers), [getting a substring](https://stackoverflow.com/questions/41105294/django-slice-a-single-field-in-a-queryset). For me it has been hard to assimilate all of the ways you can do the same thing in Django. It's nice to have options, but it's so overwhelming.... – Rne Aug 13 '18 at 21:59
2

Another approach would be creating your own custom field:

class CustomCharField(serializers.CharField):

    def __init__(self, repr_length, **kwargs):
        self.repr_length = repr_length
        super(CustomCharField, self).__init__(**kwargs)

    def to_representation(self, value):
        return super(CustomCharField, self).to_representation(value)[:self.repr_length]

And use it in serializers:

class ArticleSerializer(serializers.ModelSerializer):
    text = CustomCharField(repr_length=200)
zeynel
  • 943
  • 1
  • 8
  • 13
1

I like the 'CustomCharField' approach suggested by zeynel. This version uses Django's Truncator.

from django.utils.text import Truncator
from rest_framework import serializers

class TruncatedCharField(serializers.CharField):
    def __init__(self, length=200, **kwargs):
        self.length = length
        super().__init__(**kwargs)

    def to_representation(self, value):
        repr_ = super().to_representation(value)
        return Truncator(repr_).chars(self.length)
Matthew Hegarty
  • 3,791
  • 2
  • 27
  • 42