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

如何用函数创建父子对象的嵌套列表(Python Django场景)

问题描述

我是Python和Django新手,碰到了一个卡了很久都解决不了的问题。我的数据库里有多个对象,除了根对象外,每个对象都有一个父对象,子对象数量可以是0、1或多个。我需要写一个函数,传入某个对象(比如示例里的States),返回该对象及其所有后代组成的嵌套列表,格式如下:

arr = ['States',
       ['Kansas', ['Lawrence', 'Topeka', ['Some Topeka Street', ['Some House on Some Topeka Street']]],
        'Illinois', ['Chicago', 'Springfield']]]

我需要用这个数据结构配合Django的无序列表过滤器使用。我知道应该写递归函数,大致结构如下:

def make_nested_list(item):
    if not item.children: # 基础情况
        # 处理逻辑
    else:
        for child in item.children: # 递归情况
            # 处理逻辑
            make_nested_list(child) # 递归调用自身
    # 可能的后续处理
    # 最终返回嵌套列表
    return result 

但我尝试的所有实现都一团糟,请问该怎么实现?

更新:我的模型定义如下:

class Thing(models.Model):
    title = models.CharField(max_length=30)
    parent = models.ForeignKey('self', on_delete=models.CASCADE, blank=True,
                               null=True)

    def __str__(self):
        return self.title

    @property
    def children(self):
        return self.thing_set.all()

    @property
    def siblings(self):
        return Thing.objects.filter(parent=self.parent)
解决方案

直接用递归构建嵌套列表即可,核心逻辑是每个节点的列表以自身标题开头,再依次添加所有子节点的递归结果:

def make_nested_list(item):
    # 初始化列表,先加入当前节点的标题
    nested = [item.title]
    # 遍历所有子节点,递归生成嵌套结构并追加到当前列表
    for child in item.children:
        nested.append(make_nested_list(child))
    return nested

逻辑说明:

  • 当节点没有子节点时,item.children为空,循环不执行,直接返回仅包含自身标题的列表(比如['Lawrence'])
  • 当节点有子节点时,对每个子节点递归调用函数,得到子节点的完整嵌套结构,再把这个结构加到当前节点的列表里
  • 最终生成的结构完全匹配你需要的格式,比如传入States对象就能得到示例中的嵌套列表

优化建议:

  1. 稳定子节点顺序:如果children返回的查询集没有排序,子节点顺序可能随机,可以修改children属性加上排序:
    @property
    def children(self):
        return self.thing_set.all().order_by('title')
    
  2. 避免N+1查询:如果数据量较大,递归查询会触发多次数据库请求。可以用prefetch_related预加载所有后代节点:
    from django.db.models import Prefetch
    
    # 预加载两层子节点,层级更深可嵌套添加Prefetch
    root = Thing.objects.prefetch_related(
        Prefetch('thing_set', queryset=Thing.objects.prefetch_related('thing_set'))
    ).get(title='States')
    nested_list = make_nested_list(root)
    
    要是项目里树形结构用得频繁,推荐用django-mptt这类专门处理树形数据的库,能大幅简化查询和操作。

内容的提问来源于stack exchange,提问作者john-doe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 01:05:18