【问题标题】:Serialize model fields into nested object/dict将模型字段序列化为嵌套对象/字典
【发布时间】:2018-06-08 08:32:49
【问题描述】:

想象以下模型:

class Person(models.Model):
    name = models.CharField()
    address_streetname = models.CharField()
    address_housenumber = models.CharField()
    address_zip = models.CharField()

我有一个 django rest 框架ModelSerializer,它公开了所有字段。 但我希望能够将地址字段序列化为字典。所以当序列化为 json 输出时:

{
    name: 'Some name',
    address: {
        streetname: 'This is a test',
        housenumber: '23',
        zip: '1337',
    }
}

我尝试创建一个AddressSerializer

class Address(object):
    ...

class AddressSerializer(serializers.Serializer):
    streetname = serializers.CharField()
    housenumber = serializers.CharField()
    zip = serializers.CharField()
    ...

然后将PersonSerializer.address设置为使用AddressSerializer

class PersonSerializer(serializers.ModelSerializer):
    ...
    address = AddressSerializer()

这导致我的架构是正确的。我使用drf-yasg 生成swagger 文档。它查看序列化程序以生成正确的模型定义。所以序列化器需要表示模式。

这就是我目前所处的位置。显然现在它失败了,因为Person 模型中没有address 属性。你将如何解决这个问题?

【问题讨论】:

    标签: python django serialization django-rest-framework drf-yasg


    【解决方案1】:

    来自DRF-doc for source 说,

    source='*'有特殊含义,用于表示 整个对象应该被传递到该字段。这个可以 对于创建嵌套表示或对于 需要访问完整的对象以确定输出 表示。


    所以,试试这个,

    class AddressSerializer(serializers.Serializer):
        streetname = serializers.CharField(source='address_streetname')
        housenumber = serializers.CharField(source='address_housenumber')
        zip = serializers.CharField(source='address_zip')
    
    
    class PersonSerializer(serializers.ModelSerializer):
        # .... your fields
        address = AddressSerializer(source='*')
    
        class Meta:
            fields = ('address', 'other_fields')
            model = Person
    

    【讨论】:

      【解决方案2】:

      你可以在序列化器中定义一个property

      class Person(models.Model):
          name = models.CharField()
          address_streetname = models.CharField()
          address_housenumber = models.CharField()
          address_zip = models.CharField()
      
          @property
          def address(self):
              return {'streetname': self.address_streetname,
                      'housenumber': self.address_housenumber,
                      'zip': self.address_zip}
      

      【讨论】:

      • 是的,这可能适用于序列化。但不适用于反序列化。所以我的创建/更新操作不起作用。不过谢谢:)
      • 是的,您应该覆盖 create/update 操作。
      猜你喜欢
      • 1970-01-01
      • 2018-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多