L
L
Luke LikeSkywalker2020-01-21 06:58:31
Django
Luke LikeSkywalker, 2020-01-21 06:58:31

How can data be modified prior to serialization in Django Rest Framework?

I have 2 main models: Story and Comment

class StoryAndComment(models.Model):
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    body = models.TextField(max_length=500)
    edit_date = models.DateTimeField(auto_now=True)
    pub_date = models.DateTimeField(auto_now_add=True)

    class Meta:
        abstract = True


class Story(StoryAndComment):
    CATEGORIES_LIST = (
        ('Different', 'Different'),
        ('Funny', 'Funny'),
        ('Dirty', 'Dirty'),
        ('Scary', 'Scary'),
        ('Hatred', 'Hatred'),
        ('Weird', 'Weird'),
        ('Mystic', 'Mystic'),
        ('Shame', 'Shame'),
        ('Politics', 'Politics'),
        ('Envy', 'Envy'),
        ('Cruelty', 'Cruelty'),
        ('Laziness', 'Laziness'),
        ('Cats', 'Cats'),
        ('Childhood', 'Childhood'),
        ('Dreams', 'Dreams'),
        ('Family', 'Family'),
        ('Job', 'Job'),
        ('Happiness', 'Happiness'),
        ('Friendship', 'Friendship'),
        ('Hobby', 'Hobby'),
        ('Love', 'Love'),
        ('Music', 'Music'),
    )
    title = models.TextField(max_length=120)
    category = models.CharField(max_length=30, choices=CATEGORIES_LIST, default="Different")

    class Meta:
        verbose_name_plural = "Stories"

    def __str__(self):
        return self.title

    def get_absolute_url(self):
        return reverse("story_comments", kwargs={"pk": self.pk})


class Comment(StoryAndComment):
    story = models.ForeignKey(Story, related_name="comments", on_delete=models.CASCADE)

    class Meta:
        verbose_name_plural = "Comments"

    def __str__(self):
        return self.body[0:20] + "..."

and code for view. When the client requests a list of all posts, the code from the view is executed:
@api_view(['GET'])
@authentication_classes([SessionAuthentication, BasicAuthentication])
@permission_classes([IsAuthenticatedOrReadOnly])
def stories_list_api(request):
    if request.method == 'GET':
        stories = Story.objects.all().order_by('-pub_date')
        serializer = StorySerializer(stories, many=True)
        return Response(serializer.data)

Serialization code:
class CommentSerializer(serializers.ModelSerializer):
    comment_likes = CommentLikeSerializer(many=True, read_only=True)

    class Meta:
        model = Comment
        fields = '__all__'
        extra_kwargs = {
                        'author': {'required': False},
                        'story': {'required': False}
        }


class StorySerializer(serializers.ModelSerializer):
    comments = CommentSerializer(many=True, read_only=True)
    story_likes = StoryLikeSerializer(many=True, read_only=True)

    class Meta:
        model = Story
        fields = '__all__'
        extra_kwargs = {
                        'author': {'required': False}
        }

So the result is json where in the comments field there is an array of all comments. But since for the main page I do not need to display the comments themselves, but only their number, I need to write something in the comments field in the form of Comment.objects.all().count() for each story. The question is how do I do it. There were ideas with models.Manager in models.py itself, or when saving in serializers.py or when fetching data in views.py

Answer the question

In order to leave comments, you need to log in

2 answer(s)
Y
Yura Khlyan, 2020-01-21
@oolooq

I think you get the gist

class GroupSerializer(serializers.ModelSerializer):

    user_count = serializers.SerializerMethodField()

    class Meta:
        model = Group
        fields = ('id', 'name','user_count')

    def get_user_count(self, obj):
        return obj.user_set.count()

A
Alexander, 2020-01-21
@kentuck1213

Write another view and serializer for the main page.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question