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.
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:
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.
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.
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.