如何使用 PUT 请求在响应中发送多个字段?

How to send several fields in the response with a PUT request?

我希望当我的 PUT 请求成功时,它 return 向我发送一个包含我 PlantSerializer 中所有字段的响应,因为目前响应 return 向我发送了这个:

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

但是,我希望对 return 的回复是:

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

我怎样才能达到这个结果?

这是我的序列化器和模型 class :

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,它仅通过 fields=__all__ 值隐式包含 plant 字段。这可能导致 drf 使用 PrimaryKeyRelatedField,因此您不会获得在 PlantSerializer.

中定义的所有额外字段

如果我理解 correctyl,您希望在更新中使用 WritePlotSerializer,但在返回对象时使用 ReadPlotSerializer。您可能应该通过覆盖 update 方法将它们组合在一个序列化程序中,以支持更新嵌套的 Plant 对象。这里是 related documentation.

或者,如果您不想更新 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__'