django-mptt是一個可複用的django app, 旨在讓你本身的django項目模型使用MPTT更加簡單。它負責將數據庫表做爲樹型結構管理的詳細信息,並提供用於處理樹型模型實例的工具html
對於mptt模型算法實現不瞭解的能夠先看一下此文檔 https://www.ibase.ru/files/articles/programming/dbmstrees/sqltrees.htmlnode
pip install django-mptt # 依賴安裝包django
github地址:https://github.com/django-mptt/django-mpttpython
document:https://django-mptt.readthedocs.io/git
from django.db import models from mptt.models import MPTTModel, TreeForeignKey class Genre(MPTTModel): name = models.CharField(max_length=50, unique=True) parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
由於MPTTModel繼承自models.Model,當你的模型須要使用多繼承時,請務必將MPTTModel放在最前面,這裏跟django的mixin很類似。github
一、parent_attr 默認爲「parent」。將模型關聯回自身的字段的名稱,這樣每一個實例均可以是另外一個實例的子實例。用戶須要在模型上定義此字段如上示例的parent字段算法
二、left_attr 默認名稱"lft"。表示樹型模型字段左邊的節點數字,字段類型爲PositiveIntegerField
sql
三、right_attr 默認名稱"rght"。表示樹型模型字段右邊的節點數字,字段類型爲PositiveIntegerFieldshell
四、tree_id_attr 默認名稱"tree_id"。表示包含每一個節點的樹ID的字段的名稱數據庫
五、level_attr 默認名稱"level"。表示每一個節點所在的樹形結構的層級django
六、order_insertion_by 默認值[ ]。當插入新的樹節點或從新建立現有節點時,應定義排序的字段名列表,首先是最重要的排序字段名
根據上面的模型,生成數據庫
python manage.py makemigrations
python manage.py migrate
定義測試路由
urlpatterns = [ path('genres/', views.test_mptt), ]
定義測試視圖
from django.shortcuts import render from mptt_test.models import Genre # Create your views here. def test_mptt(request): return render(request, 'genre.html', {'genres': Genre.objects.all()})
測試模板渲染
{% load mptt_tags %} <ul> {% recursetree genres %} <li> {{ node.name }} {% if not node.is_leaf_node %} <ul class="children"> {{ children }} </ul> {% endif %} </li> {% endrecursetree %} </ul>
此時啓動django shell 插入數據(或者python console也行)
python manage.py shell
from test_mptt.models import Genre dandy = Genre.objects.create(name='dandy') elina = Genre.objects.create(name='elina') cathy = Genre.objects.create(name='cathy') Genre.objects.create(name='aaa', parent=dandy) Genre.objects.create(name='bbb', parent=elina) Genre.objects.create(name='ccc', parent=cathy)
效果圖
get_ancestors(ascending=False, include_self=False) # 返回一個包含全部當前實例祖宗的queryset get_children() # 返回包換當前實例的直接孩子的queryset(即下一級全部的子節點),按樹序排列 get_descendants(include_self=False) # 返回當前實例的全部子節點,按樹序排列 get_descendant_count() # 返回當前實例全部子節點的數量 get_family() # 返回從當前實例開始的全部家庭成員節點,用樹型結構 get_next_sibling() # 返回當前實例的下一個樹型同級節點的實例 get_previous_sibling() # 返回當前實例的上一個樹型同級節點的實例 get_root() # 獲取當前實例的根節點實例 get_siblings(include_self=False) # 獲取全部同級兄弟節點的實例的queryset insert_at(target, position='first-child', save=False) # 插入做爲目標節點的第一個子節點(若是save=True) is_child_node() # 是不是子節點 is_leaf_node() # 是不是葉節點 is_root_node() # 是不是根節點 move_to(target, position='first-child') # 移動到某個節點的第一個子節點位置,target爲空將會被移到根節點,此時不須要position位置參數 position位置參數: 'first-child', 'last-child','left', 'right'