Django Rest Framework: Как изменить структуру вывода? - PullRequest
0 голосов
/ 28 декабря 2018

Есть ли способ сгруппировать поля в Serializer / ModelSerializer или изменить структуру JSON?

Существует модель Location:

class Location(Model):
    name_en = ...
    name_fr = ...
    ...

Если я использую ModelSerializer Iполучить простое представление полей объекта, таких как:

{'name_en':'England','name_fr':'Angleterre'}

Я хочу сгруппировать некоторые поля под ключом "names", чтобы я получил

{'names':{'name_en':'England','name_fr':'Angleterre'}}

Я знаю, что могу создавать настраиваемые поля, но яхочу знать, есть ли более простой способ.Я пытался

Meta.fields = {'names':['name_en','name_fr']...}

, который не работает

Ответы [ 3 ]

0 голосов
/ 28 декабря 2018

Я думаю, что лучше использовать свойство.Вот весь пример.

class Location(models.Model):
    name_en = models.CharField(max_length=50)
    name_fr = models.CharField(max_length=50)

    @property
    def names(self):
        lst = {field.name: getattr(self, field.name)
              for field in self.__class__._meta.fields
              if field.name.startswith('name_')}
        return lst

В views:

class LocationViewSet(viewsets.ModelViewSet):
    model = models.Location
    serializer_class = serializers.LocationSerializer
    queryset = models.Location.objects.all()

И в serializers:

class LocationSerializer(serializers.ModelSerializer):
    class Meta:
        model = Location
        fields = ('id', 'names')

Мой результат для моих поддельных данных:

[{
  "id": 1,
  "names": {
      "name_en": "England",
      "name_fr": "Angleterre"}
}]
0 голосов
/ 28 декабря 2018

Вы также не можете использовать свойство в модели и использовать SerializerMethodField в вашем сериализаторе, как в этой реализации.Мы использовали здесь _meta.fields, как и в другой реализации, чтобы получить все поля, начинающиеся с name_, чтобы мы могли динамически получать желаемый результат

class LocationSerializer(serializers.ModelSerializer):
    names = serializers.SerializerMethodField()

    def get_names(self, obj):
        lst = {field.name: getattr(obj, field.name)
               for field in obj.__class__._meta.fields
               if field.name.startswith('name_')}
        return lst

    class Meta:
        model = Location
        fields = ('id', 'names')
0 голосов
/ 28 декабря 2018

Попробуйте создать упаковщик-сериализатор и поместить в него LocationSerializer

class LocationSerialzer(serializers.ModelSerialzer):
   name_en = ...
   name_fr = ...
   ...


class MySerializer(serializers.ModelSerializer):
   name = LocationSerialzer()
   ...

Используя описанный выше метод, вы можете применить свою собственную настройку, не ограничиваясь пользовательскими полями drf.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...