如何定制Django Rest Framework序列化器输出?

ere*_*eOn 9 python django json django-rest-framework

我有一个像这样的Django模型:

class WindowsMacAddress(models.Model):
    address = models.TextField(unique=True)
    mapping = models.ForeignKey('imaging.WindowsMapping', related_name='macAddresses')
Run Code Online (Sandbox Code Playgroud)

两个序列化程序,定义为:

class WindowsFlatMacAddressSerializer(serializers.Serializer):
    address = serializers.Field()

class WindowsCompleteMappingSerializer(serializers.Serializer):
    id = serializers.Field()
    macAddresses = WindowsFlatMacAddressSerializer(many=True)
    clientId = serializers.Field()
Run Code Online (Sandbox Code Playgroud)

通过视图访问序列化程序时,我得到以下输出:

[
    {
        "id": 1, 
        "macAddresses": [
            {
                "address": "aa:aa:aa:aa:aa:aa"
            }, 
            {
                "address": "bb:bb:bb:bb:bb:bb"
            }
        ], 
        "clientId": null
    }
]
Run Code Online (Sandbox Code Playgroud)

几乎不错,除了我更喜欢:

[
    {
        "id": 1, 
        "macAddresses": [
            "aa:aa:aa:aa:aa:aa",
            "bb:bb:bb:bb:bb:bb"
        ],
        "clientId": null
    }
]
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

Car*_*son 12

创建自定义序列化器字段并实现,to_native以便它返回所需的列表.

如果您使用该source="*"技术,那么这样的东西可能会起作用:

class CustomField(Field):
    def to_native(self, obj):
        return obj.macAddresses.all()
Run Code Online (Sandbox Code Playgroud)

我希望有所帮助.

更新 djangorestframework> = 3.9.1

根据文件,现在你需要重写的任意一方或双方to_representation()to_internal_value()方法.例

class CustomField(Field):
    def to_representation(self, value)
        return {'id': value.id, 'name': value.name}
Run Code Online (Sandbox Code Playgroud)


Tom*_*tie 7

卡尔顿的回答将起到很好的作用.您还可以采取其他几种方法.

您还可以使用SlugRelatedField目标上给定字段来表示关系.

所以例如......

class WindowsCompleteMappingSerializer(serializers.Serializer):
    id = serializers.Field()
    macAddresses = serializers.SlugRelatedField(slug_field='address', many=True, read_only=True)
    clientId = serializers.Field()
Run Code Online (Sandbox Code Playgroud)

或者,如果__str__WindowsMacAddress只是显示的地址,那么你可以简单地使用RelatedField,这是一个基本的只读字段,这将使你的关系目标的一个简单的字符串表示.

# models.py
class WindowsMacAddress(models.Model):
    address = models.TextField(unique=True)
    mapping = models.ForeignKey('imaging.WindowsMapping', related_name='macAddresses')

    def __str__(self):
        return self.address

# serializers.py
class WindowsCompleteMappingSerializer(serializers.Serializer):
    id = serializers.Field()
    macAddresses = serializers.RelatedField(many=True)
    clientId = serializers.Field()
Run Code Online (Sandbox Code Playgroud)

查看有关序列化程序字段文档,以便更好地了解可以在API中表示关系的各种方法.