0

I would like to add foreign key fields to DRF serializer. I need API endpoint with information of Publication details with all Comments to this publication with all Images to this publication and with Likes number to this publication.

Models

 class Publication(models.Model):
    pub_text = models.TextField(null=True, blank=True)
    pub_date = models.DateTimeField(auto_now_add=True)
    pub_author = models.ForeignKey(User, on_delete=models.CASCADE)


class Comment(models.Model):
    com_text = models.TextField(null=True, blank=True)
    com_like = models.BooleanField(default=False)
    com_author = models.ForeignKey(User, on_delete=models.CASCADE)
    com_to_pub = models.ForeignKey(Publication, on_delete=models.CASCADE, related_name='comment_author')
    com_date = models.DateTimeField(auto_now_add=True, null=True)


class Image(models.Model):
    image = models.ImageField(upload_to='images', null=True)
    image_to_pub = models.ForeignKey(Publication, on_delete=models.CASCADE, null=True, related_name='images')

Serializers

class ImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Image
        fields = ['image']


class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = ['com_text', 'com_like', 'com_date', 'com_author']


class PublicationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Publication
        fields = ['id', 'pub_text', 'pub_author', 'pub_date']

    def to_representation(self, instance):
        representation = super().to_representation(instance)
        representation['comment'] = CommentSerializer(instance.comment_author.all(), many=True).data
        representation['image'] = ImageSerializer(instance.images.all(), many=True).data
        return representation

Views

class PublicationViewSet(viewsets.ModelViewSet):
    queryset = Publication.objects.all()
    serializer_class = PublicationSerializer


class ImageViewSet(viewsets.ModelViewSet):
    queryset = Image.objects.all()
    serializer_class = ImageSerializer


class CommentViewSet(viewsets.ModelViewSet):
    queryset = Comment.objects.all()
    serializer_class = CommentSerializer

By my logik Like to Publication can be given by Comment author if comment was created. I used <to_represtntation> method to add fields to Publication serializer. It works as i would need but not sure that was a good way to do. Also i cannot imagine how to add Likes number to Publication serializer.

2 Answers 2

0

The approach you're using with the to_representation method is a valid way to customize the serialized data, but it can be improved for better clarity and performance, especially when dealing with nested relationships and adding computed fields (like the number of likes).

To enhance your approach and include the number of likes in the PublicationSerializer, we can:

Use nested serializers to display comments and images for the publication. Add a likes field to the PublicationSerializer to count the number of likes from the comments related to that publication. Optimize the to_representation approach or use SerializerMethodField to compute values like the likes count.

In Serializers You need to Update

from rest_framework import serializers
from .models import Publication, Comment, Image

class ImageSerializer(serializers.ModelSerializer):
    class Meta:
        model = Image
        fields = ['image']


class CommentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Comment
        fields = ['com_text', 'com_like', 'com_date', 'com_author']


class PublicationSerializer(serializers.ModelSerializer):
    # Nested serializers for comments and images
    comment = CommentSerializer(source='comment_author', many=True, read_only=True)
    image = ImageSerializer(source='images', many=True, read_only=True)

    # Adding a computed field for counting likes
    likes_count = serializers.SerializerMethodField()

    class Meta:
        model = Publication
        fields = ['id', 'pub_text', 'pub_author', 'pub_date', 'comment', 'image', 'likes_count']

    def get_likes_count(self, obj):
        # Count the number of likes (True) in related comments
        return obj.comment_author.filter(com_like=True).count()

Explanation:

  1. comment = CommentSerializer(source='comment_author', many=True, read_only=True): This connects the Publication model's related_name='comment_author' field to its nested comments and uses the CommentSerializer to display the comment details.

  2. image = ImageSerializer(source='images', many=True, read_only=True): Similar to comments, it connects the Publication model to its related images using the related_name='images' and uses ImageSerializer.

  3. likes_count = serializers.SerializerMethodField(): This field computes the total number of likes from the related comments for each publication. The method get_likes_count uses obj.comment_author.filter(com_like=True).count() to get the count of comments where com_like=True for the given publication.

Sign up to request clarification or add additional context in comments.

1 Comment

Azhar, mahy thanks! That really works. I also found out how to use <source> and <SerializerMethodField> to customize serializer. Point to grow up)
0

you can make object of this like

class CommentSerializer(serializers.ModelSerializer):

public=PublicationSerializer()
class Meta:
    model = Comment
    fields = ['com_text', 'com_like', 'com_date', 'com_author']

1 Comment

Thank you, Ravi Nikam. Where should I use <public> object? Should I include that object in a list of fields?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.