如何“通过”模型序列化DRF ManyToManyField?

问题描述 投票:0回答:1

我无法使 DRF 正确序列化中间“直通”模型。这是示例代码。

型号

class Track(models.Model):
    title = models.CharField(max_length=200)
    duration = models.PositiveIntegerField()

    def __str__(self):
        return self.title


class Album(models.Model):
    title = models.CharField(max_length=200)
    tracks = models.ManyToManyField(Track, through='AlbumTrack')

    def __str__(self):
        return self.title


class AlbumTrack(models.Model):
    album = models.ForeignKey(Album, on_delete=models.CASCADE)
    track = models.ForeignKey(Track, on_delete=models.CASCADE)
    score = models.PositiveIntegerField(default=0)

    class Meta:
        unique_together = ('album', 'track')

    def __str__(self):
        return f"{self.album.title} - {self.track.title} ({self.score})"

序列化器

class AlbumTrackSerializer(serializers.ModelSerializer):
    track_id = serializers.IntegerField(source='track.pk')
    track_title = serializers.CharField(source='track.title')
    track_score = serializers.CharField(source='score')

    class Meta:
        model = AlbumTrack
        fields = ('track_id', 'track_title', 'track_score')


class AlbumSerializer(serializers.ModelSerializer):
    tracks = AlbumTrackSerializer(many=True)

    class Meta:
        model = Album
        fields = ('title', 'tracks')

当我访问 /api/albums/ 时,出现异常:

Got AttributeError when attempting to get a value for field `id` on serializer `AlbumTrackSerializer`.
The serializer field might be named incorrectly and not match any attribute or key on the `Track` instance.
Original exception text was: 'Track' object has no attribute 'track'.

DRF 似乎在序列化之前将

tracks
解析为
Track
查询集。有可能阻止这种情况吗?我需要序列化
AlbumTrack
模型才能访问
score
字段。

django django-rest-framework django-serializer
1个回答
0
投票

从同事那里得到了解决方案。我必须将

source='albumtrack_set'
添加到序列化器字段中。所以,这是序列化器的工作版本。

class AlbumSerializer(serializers.ModelSerializer):
    tracks = AlbumTrackSerializer(many=True, source='albumtrack_set')

    class Meta:
        model = Album
        fields = ('title', 'tracks')
© www.soinside.com 2019 - 2024. All rights reserved.