Django Rest Framework - Nested Serializer Attribute error in response
wondering if someone could help me with the following problem.
I have a serialises such as this:
class LineupPlayerSerializer(serializers.ModelSerializer):
id = serializers.UUIDField(write_only=True)
name = serializers.CharField(read_only=True)
positionType = serializers.CharField(read_only=True)
alternativePositions = serializers.CharField(read_only=True, required=False, allow_blank=True)
shirtNumber = serializers.IntegerField(read_only=True, required=False, allow_null=True)
positionOnPitch = serializers.IntegerField(required=True)
class Meta:
model = LineupPlayer
fields = ['id', 'positionType', 'alternativePositions', 'name', 'shirtNumber', 'positionOnPitch']
def create(self, validated_data):
player_id = validated_data.pop('id')
player = Player.objects.get(id=player_id)
position_on_pitch = validated_data.pop('positionOnPitch')
lineup = validated_data.pop('lineup')
lineup_player = LineupPlayer.objects.create(lineup=lineup, player=player, positionOnPitch=position_on_pitch)
return lineup_player
class LineupSerializer(serializers.ModelSerializer):
players = LineupPlayerSerializer(many=True)
class Meta:
model = Lineup
fields = ['id', 'formation', 'players']
def create(self, validated_data):
try:
players_data = validated_data.pop('players')
lineup = Lineup.objects.create(**validated_data)
for player_data in players_data:
player_data['lineup'] = lineup
LineupPlayerSerializer().create(player_data)
return lineup
except Exception as e:
print(f"Error: {e}")
raise e
However, when I send the request I get an Attribute error:
Got AttributeError when attempting to get a value for field `positionOnPitch` on serializer `LineupPlayerReadSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Player` instance.
Original exception text was: 'Player' object has no attribute 'positionOnPitch'.
For some reason Django thinks that the positionOnPitch is in the Player model and I can't figure out how. When I use write_only=True for positionOnPitch it sends the request OK so it has only a problem when getting the positionOnPitch.
My models:
class Lineup(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
formation = models.CharField(max_length=10)
players = models.ManyToManyField(Player, through='LineupPlayer', through_fields=('lineup', 'player'))
def __str__(self):
return self.formation
class Meta:
verbose_name = "Lineup"
verbose_name_plural = "Lineups"
class LineupPlayer(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
lineup = models.ForeignKey(Lineup, on_delete=models.CASCADE, related_name='lineup')
player = models.ForeignKey(Player, on_delete=models.CASCADE, related_name='player')
positionOnPitch = models.PositiveSmallIntegerField()
def __str__(self):
return f"{self.player.name} in {self.lineup.formation}"
class Meta:
verbose_name = "Lineup Player"
verbose_name_plural = "Lineup Players"
and Player model:
class Player(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
name = models.CharField(max_length=50)
shirtNumber = models.SmallIntegerField(default=None, blank=True, null=True)
positionType = models.ForeignKey(Position, on_delete=models.CASCADE, related_name='positionType')
alternativePositions = models.ForeignKey(Position, on_delete=models.CASCADE, blank=True, null=True ,related_name='alternativePositions')
active = models.BooleanField(default=True)
injured = models.BooleanField(default=False, blank=True)
def __str__(self):
return self.name
class Meta:
verbose_name = "Player"
verbose_name_plural = "Players"
Can anyone see what could be the problem? I tried searching but couldn't find anything similar, maybe my logic is completely wrong? I have tried using copilot but that wasn't useful since it thinks there's nothing wrong with it. Any help more than welcome. I have spent already a few days on it, tried few things but getting the positionOnPitch just doesn't work. If you need any more information let me know, please. Thank you
My problem was in not using source for my LineupSerializer. After adding this the problem got solved and the serialised had access to all objects, including foreign keys in my models:
class LineupSerializer(serializers.ModelSerializer):
players = LineupPlayerSerializer(source='lineup',many=True)