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
相关产品推荐
相关产品推荐

