Django Rest框架递归嵌套父序列化

cxfofazt  于 2023-01-31  发布在  Go
关注(0)|答案(4)|浏览(165)

我有一个模型,其中包含一个名为parent的自引用字段。

class Zone(BaseModel):
    name = models.CharField(max_length=200)
    parent = models.ForeignKey('self', models.CASCADE, blank=True, null=True, related_name='children')

    def __unicode__(self):
        return self.name

串行器:

class ZoneSerializer(ModelSerializer):
    parent = PrimaryKeyRelatedField(many=False, queryset=Zone.objects.all())
    parent_disp = StringRelatedField(many=False, source="parent")

    class Meta:
        model = Zone
        fields = ('id', 'name', 'parent', 'parent_disp')

现在我想序列化区域的父级和它的父级以及它的父级,直到父级为空。我找到了子级的递归序列化方法,但没有找到父级的递归序列化方法。我该怎么做呢?

qij5mzcb

qij5mzcb1#

好吧,我已经搞定了。

class ZoneSerializer(ModelSerializer):
    parent = SerializerMethodField()

    class Meta:
        model = Zone
        fields = ('id', 'name', 'project', 'parent',)

    def get_parent(self, obj):
        if obj.parent is not None:
            return ZoneSerializer(obj.parent).data
        else:
            return None
xxls0lw8

xxls0lw82#

尝试在此处使用序列化程序方法字段:

def get_parent(self, obj):
    # query what your want here.

我不确定D-R-F是否有内置的方法,但是您可以使用query在此方法中获取您想要的内容。

jbose2ul

jbose2ul3#

您还可以执行以下操作:

class ZoneSerializer(ModelSerializer):
    class Meta:
        model = Zone
        fields = ('id', 'name', 'project', 'parent',)

    def to_representation(self, instance):
        self.fields['parent'] = ZoneSerializer(read_only=True)
        return super(ZoneSerializer, self).to_representation(instance)
gt0wga4j

gt0wga4j4#

只是想添加一个更适合我的解决方案。
上面的答案是使用SerializerMethodField,然后示例化一个新的序列化程序类,效果很好,但是如果您试图序列化一个更大的嵌套数据集,则为每个嵌套对象示例化一个新的序列化程序可能会变得相当慢。
尝试对所有嵌套对象使用序列化程序的单个示例使其速度快得多。

class ZoneSerializer(ModelSerializer):
    ...

    def get_parent(self, obj):
        if obj.parent is not None:
            return self.to_representation(obj)
        else:
            return None

还有一个步骤是将序列化程序方法字段的返回值也转换为ReturnDict示例,这是序列化程序在调用serializer.data属性时通常要做的事情。

from rest_framework.utils.serializer_helpers import ReturnDict

class ZoneSerializer(ModelSerializer):
    ...

    def get_parent(self, obj):
        if obj.parent is not None:
            return ReturnDict(self.to_representation(obj), serializer=self)
        else:
            return None

当然,这种方法也有一些潜在的缺点,比如在示例化序列化程序时会丢失验证,更难修改嵌套对象等。如果您对序列化程序设置和传递给序列化程序的数据有信心,这可能是一个很好的优化。

相关问题