Сериализатор другого типа поля - Django Rest Framework - PullRequest
0 голосов
/ 05 декабря 2018

Здравствуйте, у меня есть сериализатор, и я хотел бы иметь один тип поля для запросов GET и другое поле для запросов POST.

Это мои сериализаторы:

class TypeSerializer(serializers.Serializer):
    id = serializers.CharField()
    name = serializers.CharField(max_length=50)
    colour = serializers.CharField(max_length=8)

class UserSerializer(serializers.Serializer):
    id = UUIDField(format="hex_verbose")
    name = serializers.CharField()
    type = TypeSerializer()

Итак, ответ примерно такой:

{
    "id": "987328lf-93ad-21ba-2648-h2u7b95d5cf",
    "name": "name",
    "type": {
        "id": "RANDOM_ID",
        "name": "Type 1",
        "colour": "#ffffff"
    }
}

Это то, что я хочу на GET, но на POST IЯ хотел бы отправить полезную нагрузку следующим образом:

{
    "name": "New name",
    "type": "RANDOM_ID"
}

Я получу ошибку 500, потому что тип, как ожидается, будет словарь.

Кто-нибудь знает, возможно ли иметь одно поле дляПОЛУЧИТЬ и другое поле для POST без создания другого сериализатора?

Ответы [ 2 ]

0 голосов
/ 06 декабря 2018

Один из способов сделать это - использовать 2 поля - поле чтения и поле записи:

class TypeSerializer(serializers.Serializer):
    id = serializers.CharField()
    name = serializers.CharField(max_length=50)
    colour = serializers.CharField(max_length=8)

class UserSerializer(serializers.Serializer):
    id = UUIDField(format="hex_verbose")
    name = serializers.CharField()
    type_read = TypeSerializer(read_only=True)

    # you could use a prrimary key related field 
    # instead if it is a model serializer;
    type = serializers.CharField(write_only=True) 

    def to_representation(self, instance):
        rep = super().to_representation(instance)

        # rename type_read to type
        rep['type'] = rep['type_read']
        del rep['type_read']
        return rep
0 голосов
/ 05 декабря 2018

Вам нужно переопределить to_internal_value метод:

class UserSerializer(serializers.Serializer):
    id = UUIDField(format="hex_verbose")
    name = serializers.CharField()
    type = TypeSerializer()

    def to_internal_value(self, data):
        type = data.get('type')
        if type:
            data['type'] = {'id': type}

        ret = super(UserSerializer, self).to_internal_value(data)

        # Probably here you will need to get type instance.

        return ret

Я думаю, что вы хотите использовать этот сериализатор для создания пользователя, поэтому ему нужно больше iprovements:

# Inherit from ModelSerializer !
class UserSerializer(serializers.ModelSerializer):
    id = UUIDField(format="hex_verbose")
    name = serializers.CharField()
    type = TypeSerializer()

    class Meta:
        model = User # Set model
        fields = ('id', 'name', 'type') # Set fields

    def to_internal_value(self, data):
        type = data.get('type')
        if type:
            data['type'] = {'id': type}

        ret = super(UserSerializer, self).to_internal_value(data)

        # Here i change dict to instance
        type = ret.get('type')
        if type:
            try:
                ret['type'] = Type.objects.get(id=type['id'])
            except Type.DoesNotExist:
                raise ValidationError({'type': ['Type with the given ID does not exist.']}
        return ret
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...