代码之家  ›  专栏  ›  技术社区  ›  Milano

Django Rest框架:如何修改输出结构?

  •  0
  • Milano  · 技术社区  · 6 年前

    是否有方法对序列化程序/模型序列化程序中的字段进行分组或修改JSON结构?

    有一个 Location 型号:

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

    如果我用 ModelSerializer 对象字段的简单表示如下:

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

    我想在“names”键下分组一些字段

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

    我知道我可以创建自定义字段,但我想知道是否有更直接的方法。我试过了

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

    这不管用

    3 回复  |  直到 6 年前
        1
  •  3
  •   edilio    6 年前

    我认为最好是使用一处房产。这就是整个例子。

    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"}
    }]
    
        2
  •  1
  •   Haidar Zeineddine    6 年前

    尝试创建包装序列化程序并将LocationSerializer放在其中

    class LocationSerialzer(serializers.ModelSerialzer):
       name_en = ...
       name_fr = ...
       ...
    
    
    class MySerializer(serializers.ModelSerializer):
       name = LocationSerialzer()
       ...
    

    使用上述方法,您可以应用自己的自定义项,而不限于drf自定义字段。

        3
  •  0
  •   edilio    6 年前

    您也不能在模型上使用属性,而是使用 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')