列表字段序列化程序给出“ManyRelatedManager”对象不是 M2M 字段的可迭代错误

Ami*_*tad 5 django serialization m2m django-rest-framework

我的models.py 看起来像这样:

class IP(models.Model):
    name = models.CharField(max_length=30, unique=True)
    address = models.CharField(max_length=50, unique=True)

class IPGroup(models.Model):
    name = models.CharField(max_length=50, unique=True)
    ips = models.ManyToManyField('IP', through='IPGroupToIP')

class IPGroupToIP(BaseModel):
    ip_group = models.ForeignKey('IPGroup', on_delete=models.CASCADE)
    ip = models.ForeignKey('IP', on_delete=models.CASCADE)
Run Code Online (Sandbox Code Playgroud)

现在,为了创建 IPGroup,我有以下序列化程序:

class IPGroupCreateSerializer(serializers.ModelSerializer):
    ips = serializers.ListField()

class Meta:
    model = IPGroup
    fields = ['name', 'ips']

@transaction.atomic()
def create(self, validated_data):
    ips_data = validated_data.pop('ips', None)
    ip_group = IPGroup.objects.create(name=validated_data['name'])

    if ips_data:
        for ip in ips_data:
            ip_obj, created = IP.objects.get_or_create(name=ip['name'], address=ip['address'])
            IPGroupToIP.objects.create(ip_group_id=ip_group.id, ip_id=ip_obj.id)
    return ip_group
Run Code Online (Sandbox Code Playgroud)

我的视图是一个简单的基于类的视图,如下所示:

class IPGroupCreateView(generics.CreateAPIView):
    queryset = IPGroup.objects.get_queryset()
    serializer_class = IPGroupCreateSerializer
Run Code Online (Sandbox Code Playgroud)

我的 JSON 负载如下所示:

{ "ips": [{"name":"example.com", "address":"10.1.1.9"}], "name": "ipgroup1" }

这怎么给我一个错误说明:

/api/v1/ip-group/
'ManyRelatedManager' 对象的类型错误不可迭代

奇怪的是,当我检查数据库时,IPGroup 与 M2M ips 一起创建。因此,代码按预期工作,但视图以某种方式返回 500 服务器错误而不是创建的 201。我究竟做错了什么 ?

JPG*_*JPG 10

由于一些并发症,ListField()只有在写入数据库时才会变得方便(我不确定为什么会出现这种行为)。

在你的情况下,将write_only=TrueListField解决例外。因此IPGroupCreateSerializer将是

class IPGroupCreateSerializer(serializers.ModelSerializer):
    ips = serializers.ListField(write_only=True)
Run Code Online (Sandbox Code Playgroud)



我个人建议使用嵌套序列化程序来处理这种情况。所以,定义一个新IPSerializer类并使用它而不是serializers.ListField()

class IPSerializer(serializers.ModelSerializer):
    class Meta:
        model = IP
        fields = ('name', 'address')


class IPGroupCreateSerializer(serializers.ModelSerializer):
    ips = IPSerializer(many=True)


class Meta:
    model = IPGroup
    fields = ['name', 'ips']
Run Code Online (Sandbox Code Playgroud)

  • 那行得通!..只是为了理解,你是如何弄清楚这一点的?..我浏览了整个文档,但没有看到任何地方提到这一点.. (2认同)