Django rest framework POST много ко многим с дополнительными полями - PullRequest
3 голосов
/ 13 июня 2019

Я пытаюсь создать модель в Django, которая имеет отношение «многие ко многим» с другой моделью с дополнительными полями. Я использую остальную инфраструктуру для обеспечения CRUD-операций на них и у меня сценарий "курица-яйцо", я считаю ...

Проблема в том, что когда я иду в POST новый MainObject, он выдает ошибку в части «многие ко многим» из-за отсутствия идентификатора MainObject, на который можно указать. Но я хочу, чтобы это указывало на MainObject, который я создаю, который не существует во время POST'ing. Я считаю, что это проблема с сериализаторами, но я не уверен, как ее решить. Я предполагаю, что мои предположения также могут быть неверными в том, как я формулирую данные POST.

Я использую Django 2.1.8

Код модели

class RelatedObject(models.Model):
    ...

class MainObject(models.Model):
    related_objects = models.ManyToManyField(RelatedObject, through='ManyRelatedObject')

class ManyRelatedObject(models.Model):
    main_object = models.ForeignKey(MainObject, on_delete=models.DO_NOTHING)
    related_object = models.ForeignKey(RelatedObject, on_delete=models.DO_NOTHING)
    other_attribute = models.BooleanField(...)

Код сериализатора

class ManyRelatedObjectSerializer(serializers.ModelSerializer):
    main_object = serializers.PrimaryKeyRelatedField(queryset=MainObject.objects.all())
    related_object = serializers.PrimaryKeyRelatedField(queryset=RelatedObject.objects.all())

    class Meta:
        model = ManyRelatedObject
        fields = '__all__'


class MainObjectSerializer(serializers.ModelSerializer):
    related_object = ManyRelatedObjectSerializer(many=True)

    class Meta:
        model = MainObject
        fields = '__all__'

POST Полезная нагрузка (Предполагается, что существует RelatedObject с идентификатором 1)

{
  "related_object": [
    {
      "related_object": 1,
      "other_attribute": true
    }
  ],
  ...
}

Ответ

{
  "related_object": [
    {
      "main_object": [
        "This field is required."
      ]
    }
  ]
}

Ответ цели:

{
  "id": 1,
  "related_object": [
    {
      "main_object": 1,
      "related_object": 1,
      "other_attribute": true
    }
  ],
  ...
}

Настройка конечной точки REST

class MainObjectViewSet(viewsets.ModelViewSet):
    queryset = MainObject.objects.all()
    serializer_class = MainObjectSerializer

Ответы [ 2 ]

3 голосов
/ 14 июня 2019

Переопределить __init__() метод MainObjectSerializer.

class MainObjectSerializer(serializers.ModelSerializer):
    <b>def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.context['request'].method == 'GET':
            self.fields['related_object'] = ManyRelatedObjectSerializer(many=True)</b> 


    <b><strike>related_object = ManyRelatedObjectSerializer(many=True)</strike># remove this line</b>

    class Meta:
        model = MainObject
        fields = '__all__'

Что делает этот фрагмент, сериализатор будет отображать ответ / вывод с использованием ManyRelatedObjectSerializer сериализатора, если запрос является HTTP GET, в противном случае он будет отображать фондовый режим (PrimaryKeyRelatedField)

0 голосов
/ 25 июня 2019

Для потомков, в конечном итоге, это заклинило вручную плохо переопределенными методами create и update из-за нехватки времени.Кажется смешным, что django не может справиться с этим сценарием, похоже, что это довольно распространенный вариант использования ...

...