Когда-то давно я сделал так. Получив удовлетворение я скачал django-mptt и переделал на mptt
# Example model
class Category(models.Model):
parent = models.ForeignKey('Category',
on_delete=models.CASCADE,
verbose_name=_('Parent'),
related_name='children',
blank=True,
null=True)
title = models.CharField(_('Title'), max_length=64, unique=True)
slug = models.SlugField(max_length=50)
objects = CategoryManager()
# Manager with method to build tree using directed graph
class CategoryManager(models.Manager):
def _traverse(self, hierarchy, graph, items):
for item in items:
hierarchy.append(item)
hierarchy.append(self._traverse([], graph, graph[item.title]))
return hierarchy
def as_tree(self):
"""Returns FK hierarchy in form of nested lists."""
qs = super().get_queryset().exclude(
title='Unassigned'
).select_related('parent')
roots = []
children = []
for item in qs:
roots.append(item) if item.parent is None else children.append(item)
graph = {item.title: set() for item in qs}
sorted_children = sorted(children, key=lambda x: x.parent.title)
grouped = groupby(children, key=lambda x: x.parent.title)
for title, group in grouped:
graph[title].update(group)
return self._traverse([], graph, roots)
# To render in template in form of simple nested unordered list use built-in filter:
# https://docs.djangoproject.com/en/dev/ref/templates/builtins/#unordered-list
{{ tree|unordered_lsit }}