【问题标题】:DRF use nested serializer to create key object instead of arrayDRF 使用嵌套序列化程序来创建密钥对象而不是数组
【发布时间】:2019-07-01 22:23:34
【问题描述】:

上下文

假设我们以DRF relations guide 为例。

# models.py
class Album(models.Model):
    album_name = models.CharField(max_length=100)
    artist = models.CharField(max_length=100)

class Track(models.Model):
    album = models.ForeignKey(Album, related_name='tracks', on_delete=models.CASCADE)
    order = models.IntegerField()
    title = models.CharField(max_length=100)
    duration = models.IntegerField()

    class Meta:
        unique_together = ('album', 'order')
        ordering = ['order']

    def __str__(self):
        return '%d: %s' % (self.order, self.title)

使用序列化器会得到这个输出

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

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

会给我们这个输出:

{
    'album_name': 'Things We Lost In The Fire',
    'artist': 'Low',
    'tracks': [
        '1: Sunflower',
        '2: Whitetail',
        '3: Dinosaur Act',
        ...
    ]
}

问题

我如何使用序列化程序来获得这样的输出:

  {
    'album_name': 'Things We Lost In The Fire',
    'artist': 'Low',
    'tracks': {
        1: {order: 1, title: 'Sunflower'},
        2: {order:2, title: 'Whitetail'},
        3: {order:3, title: 'Dinosaur Act'},
        ...
    }
}

这样我们就有了一个带有轨道的对象,而不是一个数字数组。所以我可以在 javascript 中使用 this.props.album.tracks[2].title 而不是 this.props.album.tracks.find(track => track.order == 2}).title

``我有一个用例,这在 Reactjs 中似乎更方便。

我尝试过的

我考虑过覆盖to_representation 方法。但我看到这会给我一个递归循环。

class TrackSerializer(serializers.ModelSerializer):
    def to_representation(self, instance):
        print(self)
        return '%s: { %s }' % (instance.order, self.to_representation(instance))
    class Meta:
        fields = '__all__'
        model = Track

此外,我已经很好地搜索并阅读了文档。但是没有找到任何我认为应该是开箱即用的非常合乎逻辑的解决方案的解决方案。让我觉得我错了,错过了什么。

提前致谢。

【问题讨论】:

    标签: python-3.x django-rest-framework django-serializer


    【解决方案1】:

    定义一个新的 TrackSerializer 并在 AlbumSerializer 类中使用它,

    
    class TrackSerializer(serializers.ModelSerializer):
        class Meta:
            model = Track
            fields = ('id', 'order', 'title')
    
    
    class AlbumSerializer(serializers.ModelSerializer):
        tracks = TrackSerializer(many=True)
    
        class Meta:
            model = Album
            fields = ('album_name', 'artist', 'tracks')
    
        def to_representation(self, instance):
            representation = super().to_representation(instance)
            representation['tracks'] = {track['id']: track for track in representation['tracks']}
            return representation

    【讨论】:

    • 这是我已经拥有的。但这会遇到专辑对象中的曲目数组/列表。但是我想要一个轨道对象。所以我可以使用订单号直接访问曲目。我已经更新了我的问题:)
    • 覆盖 AlbumSerializerto_representation() 方法,查看我更新的答案
    • 谢谢!这工作正常。但是我希望能够从专辑端点更新曲目。当然它会让我Expected a list of items but got type \"dict\"。我尝试了一种解决方法,但无论如何都会忽略该请求。我为它创建了另一个问题stackoverflow.com/questions/56868385/…
    猜你喜欢
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 2016-03-22
    • 2020-05-04
    • 2020-12-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多