使用覆盖的to_representation更新嵌套的序列化器

时间:2019-07-03 10:46:42

标签: django django-rest-framework django-serializer

上下文

所以我有一个AlbumSerializer和一个嵌套的TrackSerializer。为了方便起见,我覆盖了AlbumSerializer的表示,以制作音轨的字典而不是列表。

class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Track
        fields = ('id', 'order', 'title')
    # directly upsert tracks
    def create(self, validated_data):
            obj, created = Track.objects.update_or_create(
            album_id= validated_data['album_id'],
            order=validated_data['order'],
            defaults={'title': validated_data['title']}
            )
            return obj


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

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

    # make a dictionary of the tracks
    def to_representation(self, instance):
        representation = super().to_representation(instance)
        representation['tracks'] = {track['id']: track for track in representation['tracks']}
        return representation

    #update tracks with the album endpoint
    def update(self, instance, validated_data):
        for track in validated_data['tracks']
            obj, created = Track.objects.update_or_create(
            album_id= track['album_id'],
            order=track['order'],
            defaults={'title': track['title']}
            )
        return instance

问题

现在,当我尝试更新专辑(包括一些曲目标题)时,我收到了Expected a list of items but got type \"dict\"。有道理。

问题

如何使DRF接受字典而不是列表(如果有曲目)?

更新:刚刚了解了drf-rw-serializers。似乎正是我所需要的。

1 个答案:

答案 0 :(得分:1)

在更新功能中,您是:

  • 试图像列表一样循环字典
  • 使用update_or_create,这将导致创建重复的曲目

这是一个错误固定代码::

def update(self, instance, validated_data):
    for trackid, track in validated_data['tracks'].items():
        obj = Track.objects.filter(id = trackid)
        if obj:
            obj[0].album_id = track['album_id']
            obj[0].order = track['order']
            obj[0].title = title= track['title']
            obj[0].save()
        else:
            Track.objects.create(
                album_id= track['album_id'],
                order=track['order'],  
                title= track['title'])
    return instance