Issue
I am having difficulties in implementing nested serializers in Django REST Framework.
I'm building an Online score board, for which I currently have three models and I'm trying to serialize it into a single response.
models.py
class Player(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
def __str__(self):
return self.first_name
class Event(models.Model):
user = models.ManyToManyField("Player")
name = models.CharField(max_length=50)
desc = models.CharField(max_length=225)
def __str__(self):
return self.name
class LeadBoard(models.Model):
"""model for LeadBoard"""
player = models.ForeignKey(Player, on_delete=models.CASCADE, related_name='leadboard_player', null=True, blank=True)
event = models.ForeignKey(Event, on_delete=models.CASCADE, related_name='leadboard_event', null=True, blank=True)
score = models.IntegerField()
def __str__(self):
return self.score
The event model represent some kind of sports events and each Event can have multiple Players (user filed in Event model), the LeadBoard model stores the score of players in each event.
serializer.py
class PlayerSerializer(serializers.ModelSerializer):
class Meta:
model = Player
fields = ('id','first_name', 'last_name', 'bio')
class EventSerializer(serializers.ModelSerializer):
user = PlayerSerializer(read_only=True, many=True)
class Meta:
model = Event
fields = ('id', 'name', 'user', 'desc')
class LeadBoardSerializer(serializers.ModelSerializer):
event = EventSerializer(read_only=True)
class Meta:
model = LeadBoard
fields = ('id', 'event', 'score')
I have added two Players
[
{
"id": 1,
"first_name": "Jhon",
"last_name": "Doe"
},
{
"id": 3,
"first_name": "Anna",
"last_name": "Doe"
}
]
and their scores in LeadBoard model
[
{
"id": 1,
"player": 1,
"event": 1,
"score": 20
},
{
"id": 2,
"player": 3,
"event": 1,
"score": 90
}
]
This is the response of LeadBoard,
[
{
"id": 1,
"event": {
"id": 1,
"name": "event2020",
"user": [
{
"id": 1,
"first_name": "Jhon",
"last_name": "Doe"
},
{
"id": 3,
"first_name": "Anna",
"last_name": "Doe"
}
],
"desc": "event description"
},
"score": 20
},
{
"id": 2,
"event": {
"id": 1,
"name": "event2020",
"user": [
{
"id": 1,
"first_name": "Jhon",
"last_name": "Doe"
},
{
"id": 3,
"first_name": "Anna",
"last_name": "Doe"
}
],
"desc": "event description"
},
"score": 90
}
]
But what I'm expecting to get is a response like this, which returns the Players(users) of events and their scores correctly.
[
{
"id": 1,
"event": {
"id": 1,
"name": "event2020",
"user": [
{
"id": 1,
"first_name": "Jhon",
"last_name": "Doe",
"score": 20
},
{
"id": 3,
"first_name": "Anna",
"last_name": "Doe",
"score": 90
}
],
"desc": "event description"
}
}
]
What am I missing here?
I'm new to Django and Django Rest Framework.
Solution
You need make response by event not by leadboard.
class PlayerSerializer(serializers.ModelSerializer):
class Meta:
model = Player
fields = ('id','first_name', 'last_name', 'bio')
class LeadBoardSerializer(serializers.ModelSerializer):
player = PlayerSerializer(read_only=True)
class Meta:
model = LeadBoard
fields = ('id', 'player', 'score')
class EventSerializer(serializers.ModelSerializer):
leadboard_event = LeadBoardSerializer(read_only=True, many=True)
class Meta:
model = Event
fields = ('id', 'name', 'desc', 'leadboard_event')
now use view to get event list
Update 1 if you want get score in player.
class PlayerSerializer(serializers.Serializer):
player_id = serializers.IntegerField()
first_name = serializers.CharField(max_length=256)
last_name = serializers.CharField(max_length=256)
score = serializers.IntegerField()
class LeadBoardSerializer(serializers.ModelSerializer):
player = serializers.SerializerMethodField()
class Meta:
model = LeadBoard
fields = ('id', 'player')
def get_player(self,obj):
player_dict = {'player_id': obj.player.id, 'first_name': obj.player.first_name, 'last_name': obj.player.last_name, 'score': obj.score}
result = PlayerSerializer(data=player_dict)
return result
class EventSerializer(serializers.ModelSerializer):
leadboard_event = LeadBoardSerializer(read_only=True, many=True)
class Meta:
model = Event
fields = ('id', 'name', 'desc', 'leadboard_event')
Try it.
Answered By - Таалай Дюшебеков
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.