Как отправить несколько полей в ответ при запросе PUT?

Я хотел бы, чтобы когда мой PUT запрос успешен, он возвращал мне ответ со всеми полями в моем PlantSerializer, потому что сейчас ответ возвращает мне следующее:

{
   "id":48,
   "name":"Jar",
   "width":"50",
   "height":"50",
   "exposure":"None",
   "qr_code":"",
   "garden":65,
   "plant":[
      7
   ]
}

Но я бы хотел, чтобы вместо этого ответ возвращал следующее:

{
   "id":48,
   "name":"Jar",
   "width":"50",
   "height":"50",
   "exposure":"None",
   "qr_code":"",
   "garden":65,
   "plant":[
      "id":7,
      "name":"Artichoke",
      "image":null
   ]
}

Как я могу достичь этого результата?

Вот мои сериализаторы и класс модели :

class Plot(models.Model):

    name = models.CharField(max_length=50)
    garden = models.ForeignKey('perma_gardens.Garden', on_delete=models.CASCADE)
    width = models.CharField(max_length=50, blank=True, null=True)
    height = models.CharField(max_length=50, blank=True, null=True)
    plant = models.ManyToManyField('perma_plants.Plant', related_name='%(class)s_plant', blank=True)

# Here is my serializers :
class GardenSerializer(serializers.ModelSerializer):
    class Meta:
        model = Garden
        fields = ('id', 'name',)

class PlantSerializer(serializers.ModelSerializer):
    class Meta:
        model = Plant
        fields = ('id', 'name', 'image')


class ReadPlotSerializer(serializers.ModelSerializer):
    garden = GardenSerializer(required=True)
    plant = PlantSerializer(many=True)
    id = serializers.IntegerField(read_only=True)

    class Meta:
        model = Plot
        fields = '__all__'
        read_only_fields = [fields]


class WritePlotSerializer(serializers.ModelSerializer):
    class Meta:
        model = Plot
        fields = '__all__'

А вот мои взгляды:

class PlotViewSet(viewsets.ModelViewSet):
    queryset = Plot.objects.all()

    def create(self, request, *args, **kwargs):
        serializer = WritePlotSerializer(data=request.data, many=isinstance(request.data, list))
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        snippet = self.get_object(pk)
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

    def partial_update(self, request, *args, **kwargs):
        instance = self.queryset.get(pk=kwargs.get('pk'))
        serializer = WritePlotSerializer(instance, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data)

    def get_serializer_class(self):
        if self.action in ("list", "retrieve"):
            return ReadPlotSerializer
        return WritePlotSerializer

В фукции partial_update вы используете WritePlotSerializer, которая имеет поле plant только неявно через значение fields=__all__. Это, вероятно, заставляет drf использовать PrimaryKeyRelatedField, и поэтому вы не получаете все дополнительные поля, которые вы определили в PlantSerializer.

Если я правильно понял, вы хотите использовать WritePlotSerializer в обновлении, но использовать ReadPlotSerializer при возврате объекта. Вероятно, вам следует объединить их оба в одном сериализаторе, переопределив метод update, чтобы поддерживать обновление вложенных объектов Plant. Вот связанная документация .

Альтернативно, если вы не хотите обновлять значения Plants, вы можете использовать слегка измененную версию ReadPlotSerializer во всех вызовах:


class PlotSerializer(serializers.ModelSerializer):
    garden = GardenSerializer(required=True, read_only=True)
    plant = PlantSerializer(many=True, read_only=True)
    id = serializers.IntegerField(read_only=True)

    class Meta:
        model = Plot
        fields = '__all__'
Вернуться на верх