我有一个与m2m关系的Django模型使用直通模型:
class ModelA(models.Model):
name = models.CharField(max_length=64)
class ModelB(models.Model):
name = models.CharField(max_length=64)
other_models = models.ManyToManyField("ModelA", through="ModelC")
class ModelC(models.Model):
model_a = models.ForeignKey("ModelA", related_name="link_to_model_a")
model_b = models.ForeignKey("ModelB", related_name="link_to_model_b")
some_other_info = models.TextField()
class Meta:
unique_together = ("model_a", "model_b", )
我想使用django-rest-framework序列化它:
class ModelCSerializer(ModelSerializer):
class Meta:
model = ModelC
fields = ('id', 'model_a', 'model_b', 'some_other_info', )
class QModelBSerializer(ModelSerializer):
class Meta:
model = ModelB
fields = ('id', 'other_models', )
other_models = ModelCSerializer(many=True, required=False, source="link_to_model_b")
现在,对于现有模型,GET正确显示:
{
"id": 2,
"name": "i am an instance of model_b",
"other_models": [
{"id": 1, "model_a": 1,"model_b": 2, "some_other_info":"here is some other info"}
],
}
但是,如果我尝试将某些数据丢失,则会失败并返回unique_together错误。我认为将此作为PUT发送会导致更新(不应该引发unique_together错误)而不是创建?这是PUT的代码:
class ModelBDetail(APIView):
def put(self, request, pk, format=None):
model = ModelB.objects.get(id=pk)
serializer = ModelBSerializer(model, data=request.data, context={"request": request})
if serializer.is_valid(): # THIS IS RETURNING FALSE
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
有什么想法吗?
答案 0 :(得分:0)
Django rest框架文档指出开发人员需要实现creates and updates for nested representations。
答案 1 :(得分:0)
尽管@Ivan对于编写我自己的创建和放大是正确的。更新fn,我看到的具体问题是嵌套序列化没有与之关联的实例属性。
新代码如下所示:
class ModelBSerializer(ModelSerializer):
....
def update(self, model_instance, validated_data):
model_c_serializer = self.fields["other_models"]
model_c_data = validated_data.pop(model_c_serializer.source, [])
for key, value in validated_data.iteritems():
setattr(model_instance, key, value)
model_instance.save()
model_c_serializer.update(model_instance.link_to_model_b.all(),
model_c_data)
return model_instance
class ModelCSerializer(ModelSerializer):
...
def to_internal_value(self, data):
# this is as good a place as any to set the instance
try:
model_class = self.Meta.model
self.instance = model_class.objects.get(pk=data.get("id"))
except ObjectDoesNotExist:
pass
return super(ModelCSerializer, self).to_internal_value(data)
基本上,我明确地为嵌套序列化程序调用{{1}},并且我还强制每个嵌套的序列化程序检查为实例传递给它们的数据。