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

如何在Django Serializers中实现递归序列化

Django序列化器实现自关联字段无限递归嵌套

问题背景

我在Django中使用序列化器时,遇到自关联字段relation_with只能递归一层的问题。以下是我的模型、当前序列化器代码、现有返回结果和期望的递归返回结果:

模型类

class TblRule(models.Model):
    rule_table_no=models.AutoField(primary_key=True)
    rule_no=models.IntegerField(blank=False)
    rule_name=models.CharField(max_length=100,blank=False)
    columns=models.CharField(max_length=100)
    data_file=models.CharField(max_length=100)
    true=models.CharField(max_length=100)


class TblCondition(models.Model):
    rule=models.ForeignKey(TblRule, on_delete=models.CASCADE,related_name='conditiontbl')
    operator=models.CharField(max_length=100)
    condition=models.CharField(max_length=100)
    relation=models.CharField(max_length=50,blank=True)
    relation_with=models.OneToOneField(to='self',null=True,blank=True,on_delete=models.CASCADE)

当前序列化器代码

class ConditionSerializers(serializers.ModelSerializer):
 
 class Meta:
     model = TblCondition
     fields = ['id','operator','condition','relation']

class ConditionSerializers(serializers.ModelSerializer):
 relation_with=ConditionSerializers(many=False)
 class Meta:
     model = TblCondition
     fields = ['id','operator','relation_with','condition','relation']


class RuleSerializers(serializers.ModelSerializer):
    conditiontbl=ConditionSerializers(many=True)
    class Meta:
        model = TblRule
        fields = ['rule_table_no','rule_no','rule_name','columns','data_file','true','conditiontbl' ]

当前API返回结果

[
    {
        "rule_table_no": 2,
        "rule_no": 1,
        "rule_name": "Age Discritization",
        "columns": "Age",
        "data_file": "Data1",
        "true": "Teen",
        "conditiontbl": [
            {
                "id": 4,
                "operator": ">",
                "relation_with": null,
                "condition": "15",
                "relation": ""
            },
            {
                "id": 5,
                "operator": "<=",
                "relation_with": {
                    "id": 4,
                    "operator": ">",
                    "condition": "15",
                    "relation": ""
                },
                "condition": "25",
                "relation": "and"
            }
        ]
    },
    {
        "rule_table_no": 3,
        "rule_no": 1,
        "rule_name": "Age Discritization",
        "columns": "Age",
        "data_file": "Data1",
        "true": "Young",
        "conditiontbl": []
    }
]

期望的递归返回结果

[
  {
    "rule_table_no": 2,
    "rule_no": 1,
    "rule_name": "Age Discritization",
    "columns": "Age",
    "data_file": "Data1",
    "true": "Teen",
    "conditiontbl": [
      {
        "id": 7,
        "operator": ">",
        "relation_with": null,
        "condition": "15",
        "relation": ""
      },
      {
        "id": 6,
        "operator": "<=",
        "relation_with": {
          "id": 7,
          "operator": ">",
          "relation_with":  
           {
            "id": 7,
            "operator": ">",
            "relation_with": null,
            "condition": "15",
            "relation": ""
          },
          "condition": "15",
          "relation": "or"
        },
        "condition": "25",
        "relation": "and"
      }
    ]
  },
  {
    "rule_table_no": 3,
    "rule_no": 1,
    "rule_name": "Age Discritization",
    "columns": "Age",
    "data_file": "Data1",
    "true": "Young",
    "conditiontbl": []
  }
]

我需要让relation_with字段实现无限层级的递归嵌套,该如何解决?


解决方案

核心思路是利用Django REST Framework序列化器的自引用特性:在定义序列化器字段时,用字符串形式引用自身类名,避免类未定义完成导致的引用错误,同时实现递归序列化。

方法一:简化写法(推荐)

直接用字符串'self'指定序列化器,DRF会自动处理无限层级的自引用:

class ConditionSerializers(serializers.ModelSerializer):
    # 用字符串引用自身序列化器,自动实现递归
    relation_with = 'self'

    class Meta:
        model = TblCondition
        fields = ['id', 'operator', 'relation_with', 'condition', 'relation']


class RuleSerializers(serializers.ModelSerializer):
    conditiontbl = ConditionSerializers(many=True)

    class Meta:
        model = TblRule
        fields = ['rule_table_no', 'rule_no', 'rule_name', 'columns', 'data_file', 'true', 'conditiontbl']

方法二:手动控制递归逻辑

如果需要自定义递归过程(比如过滤某些字段),可以使用SerializerMethodField手动处理:

class ConditionSerializers(serializers.ModelSerializer):
    relation_with = serializers.SerializerMethodField()

    def get_relation_with(self, obj):
        if obj.relation_with:
            # 递归序列化关联对象
            return ConditionSerializers(obj.relation_with).data
        return None

    class Meta:
        model = TblCondition
        fields = ['id', 'operator', 'relation_with', 'condition', 'relation']


class RuleSerializers(serializers.ModelSerializer):
    conditiontbl = ConditionSerializers(many=True)

    class Meta:
        model = TblRule
        fields = ['rule_table_no', 'rule_no', 'rule_name', 'columns', 'data_file', 'true', 'conditiontbl']

注意事项

  • 若数据存在循环关联(如A关联B,B又关联A),会导致栈溢出,需要在序列化逻辑中添加终止判断,或在模型层面避免这种循环结构;
  • 两种方法都能实现无限层级递归,选择哪种取决于是否需要自定义递归过程。

内容的提问来源于stack exchange,提问作者Pratish Dewangan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 22:15:32