You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django递归外键序列化器报错:'PolicyCondition'对象不可迭代

问题:DRF递归序列化器报错 PolicyCondition' object is not iterable

我参考了大量相关问题的解答,尝试了多个解决方案,想要在Django REST Framework的序列化器中实现递归查询。我的模型和序列化器代码如下:

模型代码

Policy模型

class Policy(TimeStampedModel):
    product = models.ForeignKey(Product, related_name='policies', on_delete=models.PROTECT, null=True)
    name = models.CharField(max_length=32)
    slug = AutoSlugField(populate_from='name', editable=True, slugify_function=slugify)

PolicyCondition模型

class PolicyCondition(TimeStampedModel):
    policy = models.ForeignKey(Policy, on_delete=models.CASCADE)
    name = models.CharField(max_length=200)
    slug = AutoSlugField(populate_from='name', editable=True, slugify_function=slugify,null=True)

    text = models.TextField()
    parent = models.ForeignKey(
        'self',
        on_delete=models.CASCADE,
        null=True,
        blank=True,
        related_name='children'
    )

序列化器代码

PolicyListSerializer

class PolicyListSerializer(serializers.ModelSerializer):
    conditions = PolicyConditionSerializer(source='policycondition_set', many=True)

    class Meta:
        model = Policy
        fields = ['conditions']

PolicyConditionSerializer

class PolicyConditionSerializer(serializers.ModelSerializer):

    class Meta:
        model = PolicyCondition
        fields = [
            'id',
            'policy',
            'name',
            'text',
            'slug',
            'parent'
        ]

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

运行时出现错误:PolicyCondition' object is not iterable,请问哪里遗漏了?


问题原因与修复方案

错误原因

你在to_representation方法中动态修改序列化器的parent字段为PolicyConditionSerializer,这种方式会干扰序列化器的实例状态:当序列化多个对象时,字段的修改会被复用,导致递归处理时,内部逻辑把单个PolicyCondition对象当成了可迭代的集合,从而抛出object is not iterable的错误。另外,通常递归查询是为了展示子节点层级结构(即每个条件下的子条件),你的代码只处理了parent字段,没有利用模型中定义的children关联,这也不符合常见的递归需求。

修复方案

根据递归展示条件层级结构的需求,推荐两种可行的写法:

方案1:使用SerializerMethodField实现递归(推荐)

这种写法逻辑清晰,便于控制递归深度和返回内容:

class PolicyConditionSerializer(serializers.ModelSerializer):
    # 递归序列化子条件
    children = serializers.SerializerMethodField()
    # 若需要展示父条件完整信息而非主键,可添加parent的SerializerMethodField
    parent = serializers.SerializerMethodField()

    class Meta:
        model = PolicyCondition
        fields = [
            'id',
            'policy',
            'name',
            'text',
            'slug',
            'parent',
            'children'
        ]

    def get_children(self, obj):
        # 存在子条件时递归序列化,否则返回空列表
        if obj.children.exists():
            return PolicyConditionSerializer(obj.children.all(), many=True, context=self.context).data
        return []

    def get_parent(self, obj):
        # 存在父条件时序列化,否则返回None
        if obj.parent:
            return PolicyConditionSerializer(obj.parent, context=self.context).data
        return None

方案2:使用DRF内置的递归序列化语法

DRF支持直接用'self'作为字段值实现递归序列化,写法更简洁:

class PolicyConditionSerializer(serializers.ModelSerializer):
    # 直接指定children为当前序列化器,实现递归
    children = 'self'
    # 若需要序列化parent,同样可以设置parent='self'
    parent = 'self'

    class Meta:
        model = PolicyCondition
        fields = [
            'id',
            'policy',
            'name',
            'text',
            'slug',
            'parent',
            'children'
        ]

注意:如果递归层级过深,可能会导致栈溢出,建议根据实际业务场景限制递归深度(比如在SerializerMethodField中添加深度参数)。


内容的提问来源于stack exchange,提问作者lord stock

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 02:24:13