I am using the django rest framework to output the content of an article. It works splendid, except now I want to modify the behavior to not return the full "content", but rather a teaser (of say the first 200 characters of the content but ideally I would like to be able to add any logic, say the end of the first sentence after 200 characters):
class ArticleSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer(many=False, read_only=True)
class Meta:
model = models.Article
fields = (
'id'
,'title'
, 'date_added'
, 'content'
, 'user'
)
I looked at GenericAPIView where I thought there may be something to override - but nothing looks obvious - can someone lend some insight? Thank you in advance
I'm pretty sure that is what you need:
http://django-rest-framework.org/api-guide/fields.html#serializermethodfield
class ArticleSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer(many=False, read_only=True)
teaser = serializers.SerializerMethodField('get_teaser')
class Meta:
model = models.Article
fields = (
'id'
,'title'
, 'date_added'
, 'user'
, 'teaser'
)
def get_teaser(self, obj):
return force_text(obj.content[:20])
I am accepting mariodev's solution - as it does work and what I was originally thinking. I did extend my requirements and want to apply the teaser functionality to other fields and thus I ended up with:
from django import forms
from rest_framework.compat import force_text
from rest_framework import serializers, fields
class TeaserField(fields.Field):
def __init__(self, teaser_length=None, original_field=None):
self.teaser_length = teaser_length
self.original_field = original_field
super(fields.Field, self).__init__()
def field_to_native(self, obj, field_name):
if(self.original_field != None):
field_name = self.original_field
value = getattr(obj, field_name)
return self.to_native(value)
def to_native(self, value):
def joinEm(chunk):
teaser = ''
i=0
while len(teaser) < self.teaser_length:
teaser += chunk[i] + '.'
i += 1
return teaser
chunk = value.split('.')
teaser = joinEm(chunk)
strongOpenTag = '<strong>'
strongOpen = teaser.find(strongOpenTag)
strongClose = teaser.find('</strong>')
if(strongOpen > 0 and strongClose < 0):
teaser = teaser.replace(strongOpenTag,'')
return force_text(teaser)
This is my current working solution, would love to know opinions on this.
from django import forms
from rest_framework.compat import force_text
class TeaserField(fields.CharField):
def __init__(self, teaser_length=None, *args, **kwargs):
self.teaser_length = teaser_length
super(TeaserField, self).__init__(*args, **kwargs)
def to_native(self, value):
return force_text(value[:self.teaser_length])
class ArticleSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer(many=False, read_only=True)
content = TeaserField(teaser_length=20)
class Meta:
model = models.Article
fields = (
'id'
,'title'
, 'date_added'
, 'content'
, 'user'
)
class IdeaSerializer(serializers.HyperlinkedModelSerializer):
user = UserSerializer(many=False, read_only=True)
teaser = myFields.TeaserField(teaser_length=200, original_field='content')
class Meta:
model = myModels.Idea
fields = (
'id'
,'title'
, 'date_added'
, 'user'
, 'content'
, 'teaser'
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With