ahsan mukhtar
ahsan mukhtar

Reputation: 442

Django Rest API. Get all data from different models in a single API call

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

Answers (3)

Shah Vipul
Shah Vipul

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

Tarun Adavani
Tarun Adavani

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

iklinac
iklinac

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

Related Questions