使用 Django REST Framework 排除嵌套序列化中的父对象

文章介绍了如何在DjangoRESTFramework中通过DynamicFieldsModelSerializer避免序列化器嵌套时的自引用字段重复,提供了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在使用 Django REST Framework 时,当序列化器嵌套在相关对象中时,如何排除父对象?

例如,我们有以下序列化器:
在这里插入图片描述

class EmployerSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Employer
        fields = ('name', 'person')

class PersonSerializer(serializers.HyperlinkedModelSerializer):
    employers = EmployerSerializer()

    class Meta:
        model = Person
        fields = ('name', 'employers')
        depth = 1

当我们访问 API http://0.0.0.0:8000/person/1/ 时,它会列出如下内容:

{
    "name": "Joe Blow",
    "employers": {
        "name": "Acme Inc."
        "person": "http://0.0.0.0:8000/person/1/"
        }
}

可以看到,“employers” 的 “person” 键是自引用的,并且是冗余的,但仅当序列化器嵌套在它所引用的对象中时才会出现这种情况。似乎应该有一个选项可以在序列化器嵌套时排除它,但我们无法找到它。

2、解决方案
我们可以使用 DynamicFieldsModelSerializer 来动态控制序列化的字段。DynamicFieldsModelSerializer 是一个自定义的序列化器类,它允许我们在初始化时指定要显示的字段或要排除的字段。

首先,我们需要定义 DynamicFieldsModelSerializer 类:

class DynamicFieldsModelSerializer(serializers.HyperlinkedModelSerializer):
    """
    A HyperlinkedModelSerializer that takes an additional `fields` argument that
    controls which fields should be displayed.
    """

    def __init__(self, *args, **kwargs):
        # Don't pass the 'fields' arg up to the superclass
        fields = kwargs.pop('fields', None)
        exclude = kwargs.pop('exclude', None)
        # Instantiate the superclass normally
        super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)

        if fields:
            # Drop any fields that are not specified in the `fields` argument.
            allowed = set(fields)
            existing = set(self.fields.keys())
            for field_name in existing - allowed:
                self.fields.pop(field_name)
        if exclude:
            # Drop fields that are specified in the `exclude` argument.
            excluded = set(exclude)
            for field_name in excluded:
                try:
                    self.fields.pop(field_name)
                except KeyError:
                    pass

然后,我们需要扩展 EmployerSerializer,使其继承 DynamicFieldsModelSerializer

class EmployerSerializer(DynamicFieldsModelSerializer):
    class Meta:
       model = Employer
       fields = ('name', 'person')

最后,我们需要在 PersonSerializer 中使用 EmployerSerializer,并将其中的 name 字段排除:

class PersonSerializer(serializers.HyperlinkedModelSerializer):
    employers = EmployerSerializer(exclude=('name',))
    class Meta:
        model = Person
        fields = ('name', 'employers')
        depth = 1

现在,当我们访问 API http://0.0.0.0:8000/person/1/ 时,它将列出如下内容:

{
    "name": "Joe Blow",
    "employers": {
        "person": "http://0.0.0.0:8000/person/1/"
        }
}

可以看到,“employers” 的 “name” 字段已经被排除掉了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值