Django Rest Framework嵌套序列化器返回响应时出现AttributeError错误求助
Django Rest Framework嵌套序列化器返回响应时出现AttributeError错误求助
兄弟,我一眼就瞅出问题所在了:当DRF返回响应的时候,它正尝试用LineupPlayerSerializer去序列化Player实例,但positionOnPitch是中间表LineupPlayer的字段,Player模型里根本没这个属性,所以才会报这个错!
为啥会出现这种乌龙?因为你的Lineup模型里的players是关联到Player的ManyToManyField,而LineupSerializer里的players字段直接用了LineupPlayerSerializer——默认情况下DRF会从Lineup.players取Player对象,而不是中间表LineupPlayer的对象,这就完全对不上号了!
给你几个具体的修复步骤,按顺序来:
1. 先修正LineupPlayer模型的关联名称
你给lineup字段设的related_name是lineup,这名字太容易和模型本身混淆了,改成更清晰的:
class LineupPlayer(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) # 把related_name改成lineup_players,这样Lineup实例能通过这个属性直接访问中间表对象 lineup = models.ForeignKey(Lineup, on_delete=models.CASCADE, related_name='lineup_players') player = models.ForeignKey(Player, on_delete=models.CASCADE, related_name='player_lineups') positionOnPitch = models.PositiveSmallIntegerField() # 其他代码保持不变
2. 修改LineupSerializer,让它序列化中间表对象
把LineupSerializer里的players字段指向中间表的关联,而不是原来的ManyToMany关联:
class LineupSerializer(serializers.ModelSerializer): # 用source指定从lineup_players(中间表关联)取数据,这样序列化的是LineupPlayer实例 players = LineupPlayerSerializer(many=True, source='lineup_players') class Meta: model = Lineup fields = ['id', 'formation', 'players'] # 这里可以优化下create方法,用save更规范 def create(self, validated_data): try: players_data = validated_data.pop('players') lineup = Lineup.objects.create(**validated_data) for player_data in players_data: LineupPlayerSerializer(data={**player_data, 'lineup': lineup}).save() return lineup except Exception as e: print(f"Error: {e}") raise e
3. 确认LineupPlayerSerializer的字段正确性
你的LineupPlayerSerializer本身没问题,positionOnPitch是LineupPlayer模型的字段,不需要额外指定source,保持原样就行:
class LineupPlayerSerializer(serializers.ModelSerializer): id = serializers.UUIDField(write_only=True) name = serializers.CharField(source='player.name', read_only=True) positionType = serializers.CharField(source='player.positionType.name', read_only=True) alternativePositions = serializers.CharField(source='player.alternativePositions.name', read_only=True, required=False, allow_blank=True) shirtNumber = serializers.IntegerField(source='player.shirtNumber', read_only=True, required=False, allow_null=True) positionOnPitch = serializers.IntegerField(required=True) class Meta: model = LineupPlayer fields = ['id', 'positionType', 'alternativePositions', 'name', 'shirtNumber', 'positionOnPitch'] # create方法保持不变
为啥之前加write_only=True能临时解决?
因为加了这个参数后,DRF返回响应时不会去序列化这个字段,自然不会傻呵呵去Player实例上找它,但这只是规避问题,不是根本解决办法。
按上面的步骤改完再测试,应该就能正常返回包含positionOnPitch的响应了!
备注:内容来源于stack exchange,提问作者Robo Gore
相关产品推荐
相关产品推荐

