【问题标题】:Django create() argument after ** must be a mapping, not list** 之后的 Django create() 参数必须是映射,而不是列表
【发布时间】:2021-01-27 10:44:16
【问题描述】:

我正在使用 DRF 创建一个可写的嵌套序列化程序,我一直在关注官方文档 (https://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers)。

我的用例与文档中给出的非常相似。

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)


serializer.py

class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Track
        fields = ['order', 'title', 'duration']

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

    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'tracks']

    def create(self, validated_data):
        tracks_data = validated_data.pop('tracks')
        album = Album.objects.create(**validated_data)
        for track_data in tracks_data:
            Track.objects.create(album=album, **track_data)
        return album

我将数据(我正在进行一些后期处理并创建此数据)传递给序列化程序的视图如下所示

注意:我正在我的视图中创建此数据。 data 据我了解是一本字典,'tracks' 有一个字典列表

views.py

@api_view(['POST'])
def my_view():
    ....
    my_data = 
    {
        'album_name': 'The Grey Album',
        'artist': 'Danger Mouse',
        'tracks': [
            {'order': 1, 'title': 'Public Service Announcement', 'duration': 245},
            {'order': 2, 'title': 'What More Can I Say', 'duration': 264},
            {'order': 3, 'title': 'Encore', 'duration': 159},
        ]
    }
    serializer = AlbumSerializer(data= my_data)
    serializer.is_valid()
    ....

现在每次我调用 my_view POST API 时,都会出现以下错误

**后的create()参数必须是映射,而不是列表

我的主要怀疑是 my_data 的格式,我相信,基于 my_data 中的错误,“轨道”应该有一个值列表作为地图对象?

我已尝试遵循堆栈溢出社区中建议的一些答案

  1. Serialize multiple models and send all in one json response django rest framework
  2. create() argument after ** must be a mapping, not list, Django REST Framework (implementing my own create method error)

我到处搜索以了解发生了什么,但我不能,任何有关这方面的线索都会非常有帮助,在此先感谢!

更新

所以我尝试通过使用验证数据是否有效

python 管理器外壳

serializer.is_valid() 返回 True,但我在保存序列化器时遇到错误

TypeError: ** 后的 create() 参数必须是映射,而不是列表

【问题讨论】:

  • album = Album.objects.create(*validated_data)?
  • 显示您的模型代码
  • @bipll 感谢您的回复,现在它抛出一个新错误 create() 需要 1 个位置参数,但给出了 7 个
  • @SuryaPratapRana 我更新了我的问题
  • data = { 'album_name': 'The Gray Album', 'artist': 'Danger Mouse', 'tracks': [ {'order': 1, 'title': '公共服务公告', 'duration': 245}, {'order': 2, 'title': '我还能说什么', 'duration': 264}, {'order': 3, 'title': 'Encore', “持续时间”:159},],}

标签: python django django-models django-rest-framework


【解决方案1】:

我通过在我的 models.py 中添加 @property 解决了这个问题

models.py

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

    @property
    def track_details(self):
        return self.track.all()

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)

序列化器.py

class TrackSerializer(serializers.ModelSerializer):
    class Meta:
        model = Track
        fields = ['order', 'title', 'duration']

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

    class Meta:
        model = Album
        fields = ['album_name', 'artist', 'tracks']

    def create(self, validated_data):
        tracks_data = validated_data.pop('tracks')
        album = Album.objects.create(**validated_data)
        for track_data in tracks_data:
            Track.objects.create(**track_data, album=album)
        return album

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-28
    • 2016-05-02
    • 2013-03-16
    相关资源
    最近更新 更多