Reputation: 442
I am trying to get all data related to model Post using one single API call. This call should include post contents, comments, upvote and downvotes.
I have 4 models and Post model is a foreign key to every other model.
class Post(models.Model):
title = models.CharField(max_length=200, null=True, blank=True)
body = models.CharField(max_length=500, null=True, blank=True)
def __str__(self):
return str(self.title)
class UpVote(models.Model):
post = models.OneToOneField(Post, related_name="upvote_post", on_delete=models.CASCADE)
upvotes = models.IntegerField(default=0)
class DownVote(models.Model):
post = models.OneToOneField(Post, related_name="downvote_post", on_delete=models.CASCADE)
downvotes = models.IntegerField(default=0)
class Comment(models.Model):
post = models.ForeignKey(Post, related_name="comment_post", on_delete=models.CASCADE)
comment = models.CharField(max_length=200, null=True, blank=True)
I saw this solution in a post to combine data with a foreign key relationship that exists.
class UpVoteSerializer(serializers.ModelSerializer):
class Meta:
model = UpVote
fields = "__all__"
class DownVoteSerializer(serializers.ModelSerializer):
class Meta:
model = DownVote
fields = "__all__"
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = "__all__"
class PostSerializer(serializers.ModelSerializer):
upvote = UpVoteSerializer(read_only=True, many=False)
downvote = DownVoteSerializer(read_only=True, many=False)
comments = CommentSerializer(read_only=True, many=True)
class Meta:
model = Post
fields = ("id", "title", "body", "upvote", "downvote", "comments")
This is from the views.py file
@api_view(['GET'])
def postList(request):
post = Post.objects.all().order_by('-id')
serializer = PostSerializer(post, many=True)
return Response(serializer.data)
This is the output that get returned
[
{
"id": 7,
"title": "1st post",
"body": "Body of 1st post"
},
{
"id": 6,
"title": "2nd post",
"body": "Body of 2nd post"
},
{
"id": 5,
"title": "3rd post",
"body": "Body of 3rd post"
},
{
"id": 4,
"title": "4th post",
"body": "Body of 4th post"
}
]
I don't know why it's not returning back the comments and the upvotes and downvotes.
Upvotes: 1
Views: 759
Reputation: 747
class allModelSerializer(serializers.Serializers):
filed1_from_model1 = serializers.CharField(max_length=10)
.....
.....
# number of fields u wants from different models
In views file just call
class viewsOne():
def get():
model1_data = model1_call
model2_data = model2_call
....
....
all_model = [model1_data,model2_data,......]
# pass a response
Upvotes: 1
Reputation: 121
Here you have defined Upvote, DownVote and Comment in another models and you have given related name to each foreign keys or OneToOne fields so, use that related name with serializers with source and you can access data of the related object.
upvote = UpVoteSerializer(read_only=True, source='upvote_post')
downvote = DownVoteSerializer(read_only=True, source='downvote_post')
comments = CommentSerializer(read_only=True, source='comment_post')
And here it is not a best practice to make another model to just keep a count of the upvote and downvote. you can easily have them in post models.
Upvotes: 1
Reputation: 15728
You do need to use related_name
to go through reverse of the relation. You might use it as source
field if you want to keep serializer field name
So for example
upvote = UpVoteSerializer(read_only=True, source='upvote_post')
Also it does not make much sense to have OneToOne
relationship to keep vote count as you could just have upvotes directly in Post model
Upvotes: 1