Django Rest Framework 自定义字段仅一对值(没有字段名作为字典键)

问题描述 投票:0回答:3

您好,我只想在 REST 服务上提供没有键的值对:

看看我的serializers.py

 class TranslationSerializer(serializers.ModelSerializer):
        translated_term = serializers.CharField(read_only=True)

        class Meta:
                model = Translation
                fields = ('language','translated_term')

class VocabSerializer(serializers.ModelSerializer):
       ...
        translates = TranslationSerializer(many=True, read_only=True)
       ...

        class Meta:
        model = Vocab
        fields = ( ..., 'translates',...)

结果如下:

"translates": [
        {
            "language": "EN",
            "translated_term": "Chair"
        }
        {
            "language": "IT",
            "translated_term": "asd"
        }
    ],

如您所见,此结果将字段名称显示为该字段值旁边的字典键。 但我想要一个不同的结构。就像下面这样:

    "translates": [
        {
            "EN": "Chair", "IT":"asd"
        }
    ],

此示例显示了一对键/值,其中键是语言字段值,字典的值是翻译字段的值。

如何仅显示“语言”字段与“已翻译”字段的一对值而不显示字段名称?

python django django-rest-framework django-serializer
3个回答
10
投票

您可以通过自定义列表序列化器来实现它

class TranslationListSerializer(serializers.ListSerializer):
    def to_representation(self, data):
        r = super().to_representation(data)

        return { item['language']: item['translated_term'] for item in r }

class TranslationSerializer(serializers.ModelSerializer):
    translated_term = serializers.CharField(read_only=True)

    class Meta:
            model = Translation
            fields = ('language','translated_term')
            list_serializer_class = TranslationListSerializer

3
投票

通过为序列化器创建自定义 to_representation 函数,您可以控制字典表示。

 class TranslationSerializer(serializers.ModelSerializer):
        translated_term = serializers.CharField(read_only=True)

        def to_representation(self, instance):
            # get the instance -> Dict of primitive data types
            representation = super(TranslationSerializer, self).to_representation(instance)

            # manipulate returned dictionary as desired
            language = representation.pop('language')
            translated_term = representation.pop('translated_term')

            # repackage
            repackaged = {language: translated_term}

            return repackaged

        class Meta:
                model = Translation
                fields = ('language','translated_term')

这将生成以下格式的 JSON

"translates": [
        {
            "EN": "Chair"
        },
            "IT": "asd"
        }
    ],

但是,这并不完全是您想要的样子,也许 VocabSerializer 的自定义“to_representation”可以实现这一点。


0
投票

我使用 SerializerMethodField 实现了它:

class VocabSerializer(serializers.ModelSerializer):
    translates = serializers.SerializerMethodField()

    def get_translates(self, obj):
        return {translation.language_code: translation.translated for translation in obj.translates_set.all()}

不是最漂亮的,但至少给出了正确的结果

© www.soinside.com 2019 - 2024. All rights reserved.