如何在DRF中获取指定分类id对应的所有子孙分类id列表
Django自关联分类模型查询所有子孙分类ID的实现方案
注意:你给出的模型类名拼写有误,应为Category而非Catgeory,同时Django 2.0及以上版本的ForeignKey字段必须指定on_delete参数,否则会触发语法错误,示例代码已经做了修正。
方案1:通用递归实现(兼容所有数据库)
逻辑简单无需额外依赖,适合分类数据量级不大的场景:
from django.db import models class Category(models.Model): name = models.CharField(max_length=100) # on_delete可根据业务需求调整为SET NULL等其他选项 parent = models.ForeignKey('self', related_name='children', on_delete=models.CASCADE, null=True, blank=True) def get_all_descendant_ids(self): descendant_ids = [] # 遍历直接子分类 for child in self.children.all(): descendant_ids.append(child.id) # 递归收集子分类的所有子孙ID descendant_ids.extend(child.get_all_descendant_ids()) return descendant_ids
调用方式:
# 查询id=2的Electronics分类的所有子孙ID electronics = Category.objects.get(id=2) result = electronics.get_all_descendant_ids() # 输出结果为 [3,4]
方案2:递归CTE实现(性能更高,推荐PostgreSQL用户使用)
仅需一次数据库查询,层级再深性能也不会明显下降,适合数据量较大的场景:
- 先安装依赖:
pip install django-cte - 模型代码:
from django.db import models from django_cte import CTEManager, CTEQuerySet class CategoryQuerySet(CTEQuerySet): def get_descendant_ids(self, root_id): # 定义递归CTE逻辑 cte = self.with_recursive( # 初始查询:获取直接子分类 cte_query=self.filter(parent_id=root_id).values("id"), # 递归查询:获取子分类的所有下级 union_all=self.filter(parent_id=cte.col.id).values("id") ) return list(cte.values_list("id", flat=True)) class Category(models.Model): name = models.CharField(max_length=100) parent = models.ForeignKey('self', related_name='children', on_delete=models.CASCADE, null=True, blank=True) objects = CTEManager.from_queryset(CategoryQuerySet)()
调用方式:
result = Category.objects.get_descendant_ids(root_id=2) # 输出结果为 [3,4]
内容的提问来源于stack exchange,提问作者coder
相关产品推荐
相关产品推荐

