Django mptt 樹狀資料結構
分類
建立時間: 2022年5月14日 02:34
更新時間: 2022年5月17日 22:50
說明
如果要在資料庫儲存像二元樹或一般樹的資料
一開始我的想法是在資料庫建立一張表,裡面有個父欄位
父欄位儲存此資料表的其他筆資料的 ID 或主鍵
假設資料如下
id | name | parent |
---|---|---|
1 | 食譜 | |
2 | 美式 | 1 |
3 | 日式 | 1 |
4 | 漢堡 | 2 |
5 | 生魚片 | 3 |
以樹狀圖呈現如下
數字為資料的 id
越上面代表輩份越大
1
/ \
2 3
/ \
4 5
也許我會想用來做清單
html 範例
<ul>
<li>食譜</li>
<ul>
<li>美式</li>
<ul>
<li>漢堡</li>
</ul>
<li>日式</li>
<ul>
<li>生魚片</li>
</ul>
</ul>
</ul>
像這樣
- 食譜
- 美式
- 漢堡
- 日式
- 生魚片
- 美式
我會在把資料取出來,用大學教的資料結構方式實現它
假 python 代碼
root = Tree()
root.text = "食譜"
data1 = Tree()
data2 = Tree()
data3 = Tree()
data4 = Tree()
data1.text = "美式"
data2.text = "漢堡"
data3.text = "日式"
data4.text = "生魚片"
data1.children = (data2)
data3.children = (data4)
root.children(data1, data3)
如上面的假代碼,這需要實作一個樹類別來走訪 root 資料
你大概可以想像用 root 來渲染出 html
大概是一個遞迴的迴圈,如果 data 是葉子就渲染 li
如果是根就渲染 li 根並遞迴根的子葉子
使用 mptt 就是要實現這個概念
之後就可以很方便的新增、修改、刪除裡面的資料
像我很清楚知道,這麼做比直接寫死在 html 還要方便
例如,我不用改程式重新部署程式,直接改資料即可
我不用實作樹類別等等…
千萬不要因為使用 mptt 而讓工作變得複雜且沒有幫助
安裝
使用 pip 安裝
pip install django-mptt
入門範例
詳細內容請參考官方文件 Turtorial -> Getting Started
我這裡的範例程式是從官方文件複製的
在 settings.py 設定
settings.py
INSTALLED_APPS = (
'django.contrib.auth',
# ...
'mptt',
)
設定 model
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')
class MPTTMeta:
order_insertion_by = ['name']
遷移資料庫
python manage.py makemigrations <your_app>
python manage.py migrate
建立一些資料
使用 django shell 快速建立,之後可以改用 admin 來操作
python manage.py shell
from myapp.models import Genre
rock = Genre.objects.create(name="Rock")
blues = Genre.objects.create(name="Blues")
Genre.objects.create(name="Hard Rock", parent=rock)
Genre.objects.create(name="Pop Rock", parent=rock)
建立 view 視圖
views.py
def show_genres(request):
return render(request, "genres.html", {'genres': Genre.objects.all()})
urls.py
(r'^genres/$', show_genres),
建立 Template 模板
genres.html
{% load mptt_tags %}
<ul>
{% recursetree genres %}
<li>
{{ node.name }}
{% if not node.is_leaf_node %}
<ul class="children">
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
admin
如果是安裝新版的可以直接註冊可拖曳版的
可以直接在畫面上拖曳資料來修改資料
from django.contrib import admin
from mptt.admin import DraggableMPTTAdmin
from myproject.myapp.models import Node
admin.site.register(
Node,
DraggableMPTTAdmin,
list_display=(
'tree_actions',
'indented_title',
# ...more fields if you feel like it...
),
list_display_links=(
'indented_title',
),
)
參考
觀看次數: 1347
djangompttpythontree
一杯咖啡的力量,勝過千言萬語的感謝。
支持我一杯咖啡,讓我繼續創作優質內容,與您分享更多知識與樂趣!