序列化器:自定义嵌套关系

时间:2019-03-31 22:58:35

标签: python django django-rest-framework

我具有以下与serializer nested relationships example中所示相似的数据结构。

型号:

class Entities(models.Model):
    name = models.CharField(max_length=100, help_text="name of the object")
    description = models.CharField(max_length=100, help_text="description of the object")

class EntitiesAVP(models.Model):
    entity = models.ForeignKey(Entities, related_name='attributes', on_delete=models.CASCADE)
    attribute = models.CharField(max_length=64, blank=False, null=True,
                                 help_text="name of the attribute")
    value = models.CharField(max_length=255, blank=False, null=True,
                             help_text="value of the attribute")

根据示例,我使用以下序列化程序在API中公开此数据:

class EntitiesAVPSerializer(serializers.ModelSerializer):
    class Meta:
        model = EntitiesAVP
        fields = ('attribute', 'value')


class EntitiesSerializer(serializers.ModelSerializer):
    attributes = EntitiesAVPSerializer(many=True, read_only=True)

    class Meta:
        model = Entities
        fields = ('name', 'description', 'attributes')

这将以以下JSON结构显示我的示例数据:

[
    {
        "name": "Test Entity",
        "description": "Description of test entity",
        "attributes": [
            {
                "attribute": "attribute 1",
                "value": "value 1"
            },
            {
                "attribute": "attribute 2",
                "value": "value 2"
            },
            {
                "attribute": "attribute 3",
                "value": "value 3"
            }
        ]
    }
]

我想要以以下格式显示我的属性:

[
    {
        "name": "Test Entity",
        "description": "Description of test entity",
        "attributes": {
                "attribute 1": "value 1"
                "attribute 2": "value 2"
                "attribute 3": "value 3"
            },
        ]
    }
]

要尝试实现这一目标,我玩过各种类型的相关领域。我能得到的最接近的是CustomRelatedField,它生成一个字符串而不是一些JSON。

class EntitiesAVPSerializer(serializers.RelatedField):
    def to_representation(self, value):
        return "{}: {}".format(value.attribute, value.value)

[
    {
        "name": "Test Entity",
        "description": "Description of test entity",
        "attributes": [
            "attribute 1: value 1",
            "attribute 2: value 2",
            "attribute 3: value 3"
        ]
    }
]

我对此很陌生,感觉离我想要达到的目标并不太远。有人可以给我一点正确的方向推动吗?

编辑:

Hugo Luis Villalobos Canto中的解决方案返回了一个字典,这是一个很棒的开始,但是它为我提供了字典列表,而不是单个字典:

class EntitiesAVPSerializer(serializers.RelatedField):
    def to_representation(self, value):
        return {value.attribute: value.value}

[
    {
        "name": "Test Entity",
        "description": "Description of test entity",
        "attributes": [
            {
                "attribute 1": "value 1"
            },
            {
                "attribute 2": "value 2"
            },
            {
                "attribute 3": "value 3"
            }
        ]
    }
]

所需的输出:

[
    {
        "name": "Test Entity",
        "description": "Description of test entity",
        "attributes": {
                "attribute 1": "value 1"
                "attribute 2": "value 2"
                "attribute 3": "value 3"
            },
        ]
    }
]

1 个答案:

答案 0 :(得分:0)

当然,您会得到一个字符串,这就是您从序列化程序的to_representation()返回的内容。

您要做的是返回字典,这就是您期望的:

class EntitiesAVPSerializer(serializers.RelatedField):
    def to_representation(self, value):
        return {value.attribute: value.value}

编辑

如果您想要的是字典,我建议您使用 SerializerMethodField ,它可以让您完全控制:

class EntitiesSerializer(serializers.ModelSerializer):
    attributes = serializers.SerializerMethodField()

    class Meta:
        model = Entities
        fields = ('name', 'description', 'attributes')

    def get_attributes(self, instance):
        attributes_dict = {}

        attributes = EntitiesAVP.objects.filter(entity=instance.entity)
        for attribute in attributes:
            attributes_dict[attribute.attribute] = attribute.value

        return attributes_dict