从 ModelSerializer 中移除嵌套

Remove nesting from ModelSerializer

我正在尝试将路由添加到 GET 和 PUT 票证状态。

class ReturnLabelTicket(models.Model):
   status = models.CharField(choices=...)

class ReturnLabelTicketStatusSerializer(serializers.ModelSerializer):
    """Serializer of a return label ticket status."""

    status = serializers.ChoiceField(ReturnLabelTicket.StatusChoice.choices)

    def to_internal_value(self, data):
        """Take the whole data value as the status."""

        return super().to_internal_value({'status': data})

    def to_representation(self, instance):
        """Return the status string."""

        return instance.status

    def update(self, instance, validated_data):
        """Update the ticket status."""

        instance.status = validated_data.get('status', instance.status)
        instance.save()
        return instance

    class Meta:
        model = ReturnLabelTicket
        fields = ['status']

默认情况下,此序列化程序期望 JSON 的形式为 { 'status': '...' },但我想删除状态键并直接使用该值。我的 to_internal_value 工作正常,但是当我删除 to_representation 中的嵌套状态时,我最终在

处遇到错误
ticketing-service    |   File "/opt/app-root/lib64/python3.9/site-packages/rest_framework/serializers.py", line 549, in data
ticketing-service    |     return ReturnDict(ret, serializer=self)
ticketing-service    |   File "/opt/app-root/lib64/python3.9/site-packages/rest_framework/utils/serializer_helpers.py", line 18, in __init__
ticketing-service    |     super().__init__(*args, **kwargs)
ticketing-service    | ValueError: need more than 1 value to unpack

这是我 ReturnLabelTicketViewSet 的相关部分。

    @action(
        detail=True,
        url_path='status',
        serializer_class=ReturnLabelTicketStatusSerializer
    )
    def status(self, _request, ticket_id=None):
        """Retrieve the ticket status."""

        ticket = self.get_object()
        serializer = self.get_serializer(ticket)
        return Response(serializer.data)

DRF 序列化程序是为 django ORM 设计的,这意味着它可以操纵 django 模型和原始字典。

我希望您直接在状态操作中绕过此行为。您可以将 to_representation 方法保留在具有本机行为的序列化程序中,并将状态操作编辑为仅 return 状态字符串(使用 serializer.instance 参数获取 serializer.instance.status 字符串和 return它在 Response 对象中....

简而言之:保留本机 to_representation 方法和 return Response(serializer.instance.status)

class ReturnLabelTicketStatusSerializer(serializers.ModelSerializer):
    """Serializer of a return label ticket status."""

    status = serializers.ChoiceField(ReturnLabelTicket.StatusChoice.choices)

    def to_internal_value(self, data):
        """Take the whole data value as the status."""

        return super().to_internal_value({'status': data})

    def update(self, instance, validated_data):
        """Update the ticket status."""

        instance.status = validated_data.get('status', instance.status)
        instance.save()
        return instance

    class Meta:
        model = ReturnLabelTicket
        fields = ['status']


@action(
    detail=True,
    url_path='status',
    serializer_class=ReturnLabelTicketStatusSerializer
)
def status(self, _request, ticket_id=None):
    """Retrieve the ticket status."""

    ticket = self.get_object()
    serializer = self.get_serializer(ticket)
    return Response(serializer.instance.status)