Удаление вложенности из 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 Serializers разработаны для django ORM, что означает, что они манипулируют моделями django и примитивными словарями.

Я предпочитаю обойти это поведение непосредственно в действии статуса. Вы можете оставить метод to_representation в вашем сериализаторе с нативным поведением и отредактировать действие status, чтобы оно возвращало только строку статуса (используйте параметр serializer.instance для получения строки serializer.instance.status и возвращайте ее в объект 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)
Вернуться на верх