簡體   English   中英

Django-rest-framework通過模型放置許多

[英]django-rest-framework PUT manytomany through model

我有一個使用直通模型的帶有m2m關系的Django模型:

models.py

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將此序列化:

serializers.py

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的代碼:

views.py

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)

有什么想法嗎?

Django rest框架文檔指出,由開發人員負責實現嵌套表示的創建和更新

盡管@Ivan在編寫自己的create&update fn上是正確的,但我看到的特定問題是嵌套序列化沒有與之關聯的instance屬性。

新代碼如下所示:

serializers.py

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)

基本上,我顯式地調用嵌套序列化程序的update ,並且我還強制每個嵌套序列化程序檢查為實例傳遞給它們的數據。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM