Django: настройка типов полей, необходимых для создания и получения сериализаторов - PullRequest
0 голосов
/ 01 ноября 2019

В настоящее время у меня есть следующий сериализатор:

serializers.py

class SurfGroupSerializer(serializers.ModelSerializer):

    instructor = SurfInstructorSerializer(many=False)
    surfers = SurferSerializer(many=True)

    class Meta:
        model = SurfGroup
        fields = ['uuid', 'instructor', 'date', 'starting_time', 'ending_time', 'surfers']

    def create(self, validated_data):
        return SurfGroup(**validated_data)

и следующий метод создания набора (набор просмотра унаследован от viewsets.ViewSet, так как нам нужна индивидуальная настройка, дополнительные сигналыи действия и т.д.):

viewsets.py

    # Surf Group Create View:
    def create(self, request, format=None):
        serializer = SurfGroupSerializer(data=request.data)

        serializer.is_valid(raise_exception=True)

        self.perform_create(serializer)

        headers = self.get_success_headers(serializer.data)

        response = responses.standardized_json_response(
            message='Surf Group Objects Have Been Successfully Created',
            data=serializer.data
        )
        return Response(data=response, status=status.HTTP_201_CREATED, headers=headers)

Для действия извлечения сериализатор работает хорошо, и у нас есть вложенный объект instructor в ответе. Однако я хочу выполнить создание, передав инструктору uuid attrbiute like (см. Содержание в текстовой области POST):

django

Вместоцелый объект ... мне было интересно, как мы этого добиваемся? Разве лучше всего иметь два сериализатора, один для выполнения создания и один для извлечения?

    def create(self, validated_data):
        surf_group = SurfGroup(
            instructor__uuid=validated_data['instructor'],
        )
        surf_group.save()
        return surf_group

1 Ответ

0 голосов
/ 02 ноября 2019

Это хороший вопрос.

Я работаю с этими ситуациями много раз, и похоже, что один вариант - иметь два сериализатора, как вы имеете в виду: 1 для списка / извлечения и 1 для сохранения.

Другой вариант (для меня) - установить в поле ввода сериализатора значение UUID, а в качестве другого данных сериализатора - как:

class SurfGroupSerializer(serializers.ModelSerializer):

    instructor = serializers.UUIDField()
    surfers = SurferSerializer(many=True, read_only=True)

    class Meta:
        model = SurfGroup
        fields = ['uuid', 'instructor', 'date', 'starting_time', 'ending_time', 'surfers']

    # I use this validate method to transform uuid to object which will
    # be bypassed to create method for easly save
    def validate_instructor(self, instructor_uuid):
        try:
            return Instructor.objects.get(uuid=instructor_uuid)
        except Instructor.DoesNotExist:
            # Remember that you dont need to pass field_key: [errors] to ValidationError
            # because validate_FIELD will automatically pass field_key for you !
            raise ValidationError(['Instructor with the given uuid does not exist.'])

    # Overwrite output data
    def to_representation(self, instance):
        ret = super().to_representation(instance)
        ret['instructor'] = SurfInstructorSerializer(instance=instance.instructor).data
        return ret
...