List Field 序列化程序给出 'ManyRelatedManager' object is not iterable error with M2M field
List Field serializer giving 'ManyRelatedManager' object is not iterable error with M2M field
我的 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)
现在,为了创建 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
我的观点是基于class的简单观点如下:
class IPGroupCreateView(generics.CreateAPIView):
queryset = IPGroup.objects.get_queryset()
serializer_class = IPGroupCreateSerializer
我的 JSON 负载如下所示:
{
"ips": [{"name":"example.com", "address":"10.1.1.9"}],
"name": "ipgroup1"
}
这怎么给我一个错误说明:
TypeError at /api/v1/ip-group/
'ManyRelatedManager' object is not iterable
奇怪的是,当我检查数据库时,IPGroup 是与 M2M ips 一起创建的。因此,代码按预期工作,但视图以某种方式返回 500 服务器错误,而不是创建的 201。我做错了什么?
由于一些并发症,ListField()
只有在写[=38=时才会派上用场] 到数据库(我不确定为什么会这样)。
在您的上下文中,在 ListField
中添加 write_only=True
解决异常。因此 IPGroupCreateSerializer
将是
class IPGroupCreateSerializer(serializers.ModelSerializer):
ips = serializers.ListField(<b>write_only=True</b>)
我个人建议使用 Nested Serializers 来处理这种情况。因此,定义一个新的 IPSerializer
class 并使用它代替 serializers.ListField()
<b>class IPSerializer(serializers.ModelSerializer):
class Meta:
model = IP
fields = ('name', 'address')</b>
class IPGroupCreateSerializer(serializers.ModelSerializer):
<b>ips = IPSerializer(many=True)</b>
class Meta:
model = IPGroup
fields = ['name', 'ips']
我有一个包含列表字段(命名社区)的序列化程序,这个列表字段的子参数是 PrimaryKeyRelatedField。
我解决这个问题的方法如下。
- 我在实例模型中定义了一个名为get_communities的方法。
- 在序列化程序的 to_representation 方法中弹出列表字段。
- 呼叫超级
- 使用更新方法更新 returned 值,因为它是一个字典。
- 和 return 更新后的 ret。
def to_representation(self, instance):
if isinstance(instance, OrderedDict):
return super(SerializerClassName, self).to_representation(instance)
self.fields.pop('communities')
ret = super(SerializerClassName, self).to_representation(instance)
ret.update({'communities': instance.get_communities()})
return ret
我的 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)
现在,为了创建 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
我的观点是基于class的简单观点如下:
class IPGroupCreateView(generics.CreateAPIView):
queryset = IPGroup.objects.get_queryset()
serializer_class = IPGroupCreateSerializer
我的 JSON 负载如下所示:
{ "ips": [{"name":"example.com", "address":"10.1.1.9"}], "name": "ipgroup1" }
这怎么给我一个错误说明:
TypeError at /api/v1/ip-group/
'ManyRelatedManager' object is not iterable
奇怪的是,当我检查数据库时,IPGroup 是与 M2M ips 一起创建的。因此,代码按预期工作,但视图以某种方式返回 500 服务器错误,而不是创建的 201。我做错了什么?
由于一些并发症,ListField()
只有在写[=38=时才会派上用场] 到数据库(我不确定为什么会这样)。
在您的上下文中,在 ListField
中添加 write_only=True
解决异常。因此 IPGroupCreateSerializer
将是
class IPGroupCreateSerializer(serializers.ModelSerializer):
ips = serializers.ListField(<b>write_only=True</b>)
我个人建议使用 Nested Serializers 来处理这种情况。因此,定义一个新的 IPSerializer
class 并使用它代替 serializers.ListField()
<b>class IPSerializer(serializers.ModelSerializer):
class Meta:
model = IP
fields = ('name', 'address')</b>
class IPGroupCreateSerializer(serializers.ModelSerializer):
<b>ips = IPSerializer(many=True)</b>
class Meta:
model = IPGroup
fields = ['name', 'ips']
我有一个包含列表字段(命名社区)的序列化程序,这个列表字段的子参数是 PrimaryKeyRelatedField。
我解决这个问题的方法如下。
- 我在实例模型中定义了一个名为get_communities的方法。
- 在序列化程序的 to_representation 方法中弹出列表字段。
- 呼叫超级
- 使用更新方法更新 returned 值,因为它是一个字典。
- 和 return 更新后的 ret。
def to_representation(self, instance):
if isinstance(instance, OrderedDict):
return super(SerializerClassName, self).to_representation(instance)
self.fields.pop('communities')
ret = super(SerializerClassName, self).to_representation(instance)
ret.update({'communities': instance.get_communities()})
return ret