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',
    ),
)

參考

django-mptt 文件
django-mptt Github

觀看次數: 910
djangompttpythontree
按讚追蹤 Enjoy 軟體 Facebook 粉絲專頁
每週分享資訊技術

一杯咖啡的力量,勝過千言萬語的感謝。

支持我一杯咖啡,讓我繼續創作優質內容,與您分享更多知識與樂趣!