только для чтения, но все еще заполняется в методе create в сериализаторе

#python #django #django-rest-framework

#питон #django #django-rest-фреймворк #python

Вопрос:

У меня есть пользовательский метод create в моем сериализаторе для добавления тегов, где потребитель может отправлять полезную нагрузку исключительно с tags ключом, содержащим список имен тегов.

 {
"id": 1,
"title": "Testing",
...
"tags": ["Python", "Django", "Go"]
}
  

Сериализатор:

 class StreamSerializer(serializers.HyperlinkedModelSerializer):
    streamer = StreamerSerializer()
    tags = TagSerializer(many=True)

    class Meta:
        model = Stream
        fields = [
            "id",
            "source",
            "stream_id",
            "started_at",
            "collected_at",
            "title",
            "thumbnail_url",
            "viewer_count",
            "video_type",
            "language",
            "streamer",
            "stream_data",
            "tags",
            "live_now",
        ]

        extra_kwargs = {"tags": {"validators": []}}

    def create(self, validated_data):
        # pop streamer and tags from the payload
        print(validated_data)
        streamer_data = validated_data.pop("streamer")
        tag_names = validated_data.pop("tags")

        # get_or_create the streamer for this stream
        streamer_user_id = streamer_data.pop("user_id")
        streamer, created = Streamer.objects.get_or_create(
            user_id=streamer_user_id, defaults=streamer_data
        )

        # use get_or_create on the stream to prevent duplicates if stream
        # crashes or a node change and just update the existing stream
        # with new data instead.
        stream, created = Stream.objects.get_or_create(
            streamer=streamer, defaults=validated_data
        )

        # add tags to the newly created stream
        for tag_name in tag_names:
            tag = Tag.objects.get(name=tag_name)
            stream.tags.add(tag.id)

        stream.save()
        return stream
  

Я бы хотел, чтобы теги имели read_only=True , но, делая это, я получаю KeyError при отправке в эту конечную точку, поскольку теперь это исключено из любых методов записи.

 class StreamSerializer(serializers.HyperlinkedModelSerializer):
    streamer = StreamerSerializer()
    tags = TagSerializer(many=True, read_only=True) # add read_only
    ...
  

Что я мог бы сделать, чтобы не иметь тегов, необходимых для проверки, но при этом иметь доступ к полю в моем create методе? Нужен ли мне для этого пользовательский валидатор?

Ответ №1:

Это не совсем отвечает на вопрос, но достигает цели, которую я собираюсь использовать to_internal_value на своем TagSerializer .

 class TagSerializer(serializers.HyperlinkedModelSerializer):
    parent = ParentTagSerializer()

    class Meta:
        model = Tag
        fields = ["name", "aliases", "parent"]

        extra_kwargs = {"aliases": {"validators": []}}

    # to_internal_value will iterate each tag name in the post payload
    # and return the tag matching that name.
    def to_internal_value(self, tag_name):
        tag = Tag.objects.get(name=tag_name)
        return tag


class StreamSerializer(serializers.HyperlinkedModelSerializer):
    streamer = StreamerSerializer()
    tags = TagSerializer(many=True)
    ...