Десериализовать имена других полей, чем имена атрибутов - PullRequest
0 голосов
/ 20 июня 2019

Я хотел бы десериализовать ввод, указанный как:

{
    "NameFilter": ["John", "Paul"],  # name has to be exactly 4 letters length
    "AgeFilter": [
        {
            "Min": 10,
            "Max": 12
        },
        {
            "Min": 8,
            "Max": 99
        }
    ]
}

Примерно так:

{
    'name_filter': ['John', 'Paul'],
    'age_filter': ['10-12', '8-99']
}

Для этого я создал 3 сериализатора:

class NameFilterSerializer(serializers.Serializer):
    name_filter = serializers.CharField(max_length=4, validators=[MinLengthValidator(4)])

    def to_representation(self, instance):
        return instance


class AgeFilter(serializers.Serializer):
    min = serializers.IntegerField()
    max = serializers.IntegerField()

    def to_representation(self, instance):
        return str(instance['Min']) + '-' + str(instance['Max'])



class FilterSerializer(serializers.Serializer):
    name_filter = NameFilterSerializer(many=True)
    age_filter = AgeFilter(many=True)

    def to_internal_value(self, data):
        return {
            'name_filter': data['NameFilter'],
            'age_filter': data['AgeFilter']
        }

Возвращает правильные значения, но в случае неверных входных данных («Min» не является числом или «NameFilter» содержит «NameExceeding4letters»), это не вызывает ошибку. Чего мне не хватает?

Пример неверных данных:

{
    "NameFilter": ["VeryLongName", "Paul"],  # name has to be exactly 4 letters length
    "AgeFilter": [
        {
            "Min": 'I am not an int',
            "Max": 12
        },
        {
            "Min": 8,
            "Max": 99
        }
    ]
}```

1 Ответ

0 голосов
/ 20 июня 2019

Вы можете создать настраиваемое поле сериализатора, которое отображает ошибку преобразования перед фактическим отображением ресурса:

from django.utils import six


class ValidIntegerField(serializers.IntegerField):
    def to_internal_value(self, data):
        if isinstance(data, six.text_type):
            raise serializers.ValidationError('Value should be a valid integer')

        return super().to_internal_value(data)

А затем используйте его в определении класса сериализатора:

class AgeFilter(serializers.Serializer):
    min = ValidIntegerField()
    max = ValidIntegerField()

    def to_representation(self, instance):
        return str(instance['Min']) + '-' + str(instance['Max'])

Примечание : Документы о six.text_type

...