2015-09-15 3 views
0

У меня есть Django модель ж/отношения m2m, которая использует сквозную модель:Джанго-отдых-основа PUT manytomany через модель

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- остальные-основа:

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 отображает properl y:

{ 
    "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) 

Есть мысли?

+0

Вы отправили результат GET, когда вы его разместили? – Ivan

+0

@ Иван - Да, никаких изменений. – trubliphone

ответ

0

Несмотря на то, что @Ivan был прав в написании моего собственного обновления &, конкретная проблема, которую я видел, заключалась в том, что вложенная сериализация не имела связанного с ней атрибута экземпляра.

Новый код выглядит следующим образом:

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 для вложенных сериализаторов явно, и я также заставить каждый вложенный сериалайзер для проверки данных, который передается их для экземпляра.

Смежные вопросы