Django REST: Save Many-to-Many Association with many=True



场景

我在两种型号之间有一种多对多的关系:

供应商

class Supplier(models.Model):
class Meta:
unique_together = ['supplier_no', 'supplier_name']
ordering = ['supplier_name']
supplier_no = models.IntegerField(blank=False, null=False)
supplier_name = models.CharField(max_length=180)
...
updated = models.DateTimeField(auto_now=True, blank=True)
updated_by = models.ForeignKey(UsaUser, on_delete=models.CASCADE, blank=True, null=True,
related_name='supplierUpdatedByUser')
def __str__(self):
return self.supplier_name

工厂

class Plant(models.Model):
class Meta:
unique_together = ['plant_no', 'plant_name']
ordering = ['plant_no']
plant_no = models.IntegerField(unique=True)
plant_name = models.CharField(max_length=180, unique=True)
...
suppliers = models.ManyToManyField(Supplier, related_name='plants')
updated = models.DateTimeField(auto_now=True, blank=True)
updated_by = models.ForeignKey(UsaUser, on_delete=models.CASCADE, blank=True, null=True,
related_name='plantUpdatedByUser')
def __str__(self):
return self.plant_name

简单地说:一个供应商可以活跃在任何数量的工厂中,一个工厂可以有任何数量的供应商。

这是SupplierSerializer,其创建方法有问题:

class SupplierSerializer(serializers.ModelSerializer):
plants = PlantSerializer(many=True)  # serializes entire supplier objects instead of just returning the pk
class Meta:
model = Supplier
fields = ['id', 'supplier_no', 'supplier_name', ... 'plants']
def create(self, validated_data):
# Add the UsaUser as a blameable field, which will be passed in the 'context' object to the serializer.
validated_data.update({"updated_by": self.context['request'].user})
assoc_plants = validated_data.pop('plants')  # remove the many-to-many association from the data before saving
supplier = Supplier.objects.create(**validated_data)
# Now add in the associated plants
for plant in assoc_plants:
supplier.plants.add(plant)
return supplier
...

问题:

创建供应商时,我得到以下400响应:

{"plants":[{"non_field_errors":["Invalid data. Expected a dictionary, but got int."]},{"non_field_errors":["Invalid data. Expected a dictionary, but got int."]}]

如果我从序列化程序中删除以下行:

plants = PlantSerializer(many=True)

问题解决了。然而,我希望完整的植物对象返回到我的前端,而不仅仅是植物ID。

我想也许我需要返回完整的Plant对象,因为错误表明它正在查找字典,但后来我又遇到了另一个错误:

{"plants":[{"plant_no":["plant with this plant no already exists."],"plant_name":["plant with this plant name already exists."]}]}

样本请求有效载荷

{"供应商编号":"5052","供应商名称":"我的供应商","is_active":true,"植物":[1,10]}

^^1和10是植物的pk

通过整个工厂对象时:

{quot;supplier_no":"54564","supplier_name":"MySuppeir","is_active":true,"plants":[{quot;id"1,"plant_no":1,"plant_name":"AutoPlant1","is _active"}]}

我认为您希望使用已经创建的植物。然后您可以使用一些额外的字段。

class SupplierSerializer(serializers.ModelSerializer):
plants = PlantSerializer(many=True, read_only = True)  # set it as read_only
plant_ids = serializers.ListField(
child = serializers.IntegerField(),
write_only = True
)
class Meta:
model = Supplier
fields = [..., 'plant_ids'] # add plant_ids
def create(self, validated_data):        
plant_ids = validated_data.pop('plant_ids')
supplier = Supplier.objects.create(**validated_data)
supplier.plants.set(plant_ids)
return supplier

最新更新