Место в документации:
https://django-mptt.readthedocs.io/en/latest/tutor...
Пример использования в Интернет-магазине для вывода выпадающего каталога товаров:
https://github.com/ri-gilfanov/python-t/blob/maste...
Если лень вчитываться в весь шаблон, вот вкратце:
{% load static mptt_tags %}
{% recursetree category_tree %}
<li>
<a class="btn btn__light" href="{% url 'category' node.pk %}">
<span style="flex: 1 1 auto;">{{ node.name }}</span>{% if not node.is_leaf_node %}
<span> </span><span class="fa fa-angle-right"></span>{% endif %}
</a>
{% if not node.is_leaf_node %}
<ul class="site_nav_primary__submenu ul__column white_box">
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
Переменная шаблона category_tree -- это дерево категорий, формируемое в контекст-процессоре, посмотреть его можно тут:
https://github.com/ri-gilfanov/python-t/blob/maste...
А модель категорий можно найти тут:
https://github.com/ri-gilfanov/python-t/blob/maste...
В разметке из шаблона выше, каждый элемент дерева категорий именуется node (т.е. узел). В общем-то, это обычный объект модели Django ORM.
Скажем, формирование ссылки:
<a class="btn btn__light" href="{% url 'category' node.pk %}"></a>
В одном из urls.py есть route (маршрут) с именем category, принимающий id категории. Обычно, node.pk и node.id -- это одно и то же, но я предпочитаю брать .pk, чтобы независеть от реального названия первичного ключа.
А вот этот фрагментик из фрагмента выше:
{% if not node.is_leaf_node %}
<ul class="site_nav_primary__submenu ul__column white_box">
{{ children }}
</ul>
{% endif %}
...значит следующее. Если узел (node) верхнего уровня содержит дочерние узлы, то мы делаем вложенные маркерованные списки (ul) с особыми стилями CSS, а переменная {{ children }} означает, что внутри тегов с каждым дочерним элементом будет происходить всё то же самое, что и с узлами верхнего уровня.
Если псевдокодом на русском:
{% рекурсивное_дерево дерева_категорий %}
Открываем HTML-теги для узлов верхнего уровня
и что-то делаем с узлами верхнего уровня.
{% если узел верхнего уровня содержит дочерние узлы %}
открываем html-теги, в которые хотим завернуть дочерние узлы
{{ дети }}
закрываем html-теги
{% конец если про детей %}
Если нужно, ещё что-то делаем с узлами верхнего уровня
и закрываем HTML-теги.
{% конец рекурсивного дерева %}
Правда, в примере из интернет-магазина, я делаю проверку на наличие дочерних узлов дважды.
Первый раз, я использую её чтобы добавить "небездетным" узлам иконку со стрелочкой, чтобы пользователь знал, что можно навести мышкой и выпадут дочерние категории.
Таким образом, эту проверку можно использовать в разных местах, если нужно по-разному оформить узды с детьми и узлы без детей.
Извиняюсь, если изложил немного путанно. Однако, разобраться во всех возможностях django-mptt можно за один вечер. Документация есть, а при сложностях с английским можно воспользоваться онлайн-переводчиками.