Сериализаторы: настройка вложенных отношений - PullRequest
1 голос
/ 01 апреля 2019

У меня есть следующая структура данных, которая похожа на ту, что показана в примере вложенных отношений сериализатора .

Модели:

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 голосов
/ 01 апреля 2019

Конечно, вы получаете строку, вот что вы возвращаете из сериализатора to_representation().

Что вам нужно сделать, это вернуть словарь, то, что вы ожидаете:

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

EDIT

Если вам нужен словарь, я советую вам использовать 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...