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

Python中如何对Django Model查询数据实现深度优先前序排序

问题原因

原代码的逻辑存在2个核心问题:

  • 没有将Django QuerySet显式转为列表,多次迭代QuerySet会触发重复的数据库查询,导致内层循环拿不到子节点数据
  • 原有双重循环逻辑仅支持2级主题结构,嵌套层级超过2级时无法正确遍历

解决方案

采用深度优先遍历(DFS)实现任意层级的前序排序,全程直接操作Django Model实例,无需转JSON:

from collections import defaultdict

# 1. 一次性查询所有主题并转为列表,避免后续重复查询数据库
all_topics = list(Topics.objects.all())

# 2. 按parent_id分组构建子节点映射,每组内先按order升序排序
child_topic_map = defaultdict(list)
for topic in all_topics:
    child_topic_map[topic.parent_id].append(topic)
for parent_id in child_topic_map:
    child_topic_map[parent_id].sort(key=lambda item: item.order)

# 3. 深度优先遍历构建排序结果
sorted_topics = []
# 先取所有顶级节点(parent_id为None)并按order升序排序
root_topics = sorted(child_topic_map.get(None, []), key=lambda item: item.order)

def dfs(current_topic):
    sorted_topics.append(current_topic)
    # 递归遍历当前节点的所有子节点
    for child in child_topic_map.get(current_topic.id, []):
        dfs(child)

for root in root_topics:
    dfs(root)

最终得到的sorted_topics就是符合要求的排序后的Model实例列表。

轻量修复方案(仅支持2级嵌套)

如果不需要支持多层级嵌套,只想修复原有代码,仅需先把QuerySet转为列表即可:

# 先转列表,避免多次迭代的问题,注意排序字段要和实际Model字段对应
topics_test = list(Topics.objects.order_by('order', 'parent_id'))
topics_ordered = []
for topic in topics_test:
    # 只处理顶级节点,子节点统一在内层添加
    if not topic.parent_id:
        topics_ordered.append(topic)
        # 筛选当前父节点的子节点,按order排序后添加
        sub_topics = sorted([t for t in topics_test if t.parent_id == topic.id], key=lambda x:x.order)
        topics_ordered.extend(sub_topics)

内容的提问来源于stack exchange,提问作者Maaschtj Djeevta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 08:24:05