DRF 使用嵌套序列化程序创建键对象而不是数组
DRF use nested serializer to create key object instead of array
上下文
假设我们从 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
此外,我已经很好地搜索和阅读了文档。但是没有找到任何我认为应该是开箱即用的非常合乎逻辑的解决方案的解决方案。让我觉得我错了,漏掉了什么。
提前致谢。
定义一个新的 TrackSerializer
并在 AlbumSerializer
class 中使用它作为,
<b>class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ('id', 'order', 'title')</b>
class AlbumSerializer(serializers.ModelSerializer):
<b>tracks = TrackSerializer(many=True)</b>
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
<b> def to_representation(self, instance):
representation = super().to_representation(instance)
representation['tracks'] = {track['id']: track for track in representation['tracks']}
return representation</b>
上下文
假设我们从 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
此外,我已经很好地搜索和阅读了文档。但是没有找到任何我认为应该是开箱即用的非常合乎逻辑的解决方案的解决方案。让我觉得我错了,漏掉了什么。
提前致谢。
定义一个新的 TrackSerializer
并在 AlbumSerializer
class 中使用它作为,
<b>class TrackSerializer(serializers.ModelSerializer):
class Meta:
model = Track
fields = ('id', 'order', 'title')</b>
class AlbumSerializer(serializers.ModelSerializer):
<b>tracks = TrackSerializer(many=True)</b>
class Meta:
model = Album
fields = ('album_name', 'artist', 'tracks')
<b> def to_representation(self, instance):
representation = super().to_representation(instance)
representation['tracks'] = {track['id']: track for track in representation['tracks']}
return representation</b>