1. 程式人生 > >Django+zTree構建組織架構樹

Django+zTree構建組織架構樹

樹,因其清晰明瞭的展現形式而被廣泛的使用

日常的開發過程中我們需要經常與“樹”打交道,例如公司的組織架構樹、伺服器的專案歸屬樹,管理後臺側邊樹等等,本篇文章介紹關於樹的兩個內容

  1. 多功能的前端樹外掛zTree
  2. Django中關於樹的model設計

zTree

zTree是一個開源的依靠JQuery實現的多功能樹外掛,具有效能優異、配置靈活、功能強大的特點

之前的系列前端外掛文章已經多次介紹過將前端外掛引入自己專案中的方法,這裡就不贅述了,如有問題也可以參考文章末尾給出的Demo程式碼,在引入JS/CSS之後只需要如下程式碼即可構建一顆樹

<ul id="treeDemo" class="ztree"></ul>

<script>
    var setting = {
      data: {
        simpleData: {
          enable: true
        }
      }
    };

    var zNodes = [
      {id: 1, pId: 0, name: "OPS-COFFEE ", open: true},
      {id: 2, pId: 1, name: "運營部", open: true},
      {id: 3, pId: 1, name: "市場部", open: true},
      {id: 4, pId: 1, name: "綜合部", open: true},
      {id: 5, pId: 2, name: "產品部", open: true},
      {id: 6, pId: 2, name: "技術部", open: true},
      {id: 7, pId: 3, name: "銷售部", open: true},
      {id: 8, pId: 4, name: "人事部", open: true},
      {id: 9, pId: 4, name: "財務部", open: true},
    ];

    $.fn.zTree.init($("#treeDemo"), setting, zNodes);
</script>

$.fn.zTree.init初始化樹,這裡需要三個引數,第一個引數是載入樹結構的Jquery物件,setting為ztree的各種配置引數,zNodes為ztree的具體資料

zTree的配置採用json的格式,按照配置型別分為了介面配置view,資料配置data,編輯配置edit,複選框配置check,非同步載入配置async以及各種回撥函式配置callback,配置豐富且強大

zTree支援兩種資料模式,簡單資料模式和標準資料模式,簡單資料模式就像我們上邊例子中這樣的資料結構,而標準資料模式就需要將資料構造成複雜的JSON巢狀格式,像下邊這樣

var zNodes = [{
  "name": "OPS-COFFEE",
  "open": true,
  "children": [
      {
          "name": "運營部",
          "open": true,
          "children": [
              {"name": "產品部","open": true},
              {"name": "技術部","open": true}
          ]
      },
      {
          "name": "市場部",
          "open": true,
          "children": [
              {"name": "銷售部","open": true}
          ]
      },
      {
          "name": "綜合部",
          "open": true,
          "children": [
              {"name": "人事部","open": true},
              {"name": "財務部","open": true}
          ]
      }
  ]
}];

標準模式資料結構複雜但父子關係清晰,簡單模式資料則相反,示例中我們使用了簡單資料模式,需要配置simpleData的enable屬性為true

完成以上配置後可以看到頁面效果如下

Django

既然前端頁面已經能夠正常展示樹了,後端就只需要返回前端對應的資料格式即可,Django中最簡單的方式就是使用Foreignkey的自關聯,模型設計如下:

class Department(models.Model):
    name = models.CharField(
        max_length=128, unique=True, verbose_name='名稱')
    parent = models.ForeignKey(
        'self', on_delete=models.PROTECT, db_constraint=False,
        null=True, blank=True, verbose_name='父部門')

ForeignKey第一個引數用self就表示自關聯,自己關聯自己,還有兩個Foreignkey的重要引數解釋如下:

on_delete: 控制當外來鍵引用的物件被刪除時指定的SQL約束行為

  • CASCADE:級聯刪除,當你刪除資料時與之關聯的也會刪除
  • PROTECT:保護模式,當你刪除資料時會丟擲ProtectedError的錯誤
  • SET_NULL:設定為空,當你刪除資料時外來鍵欄位被設定為空,前提是有設定null=True, blank=True
  • SET_DEFAULT:設定預設值,當你刪除資料時外來鍵欄位設定為預設值,前提是有設定default
  • DO_NOTHING:什麼也不做,但這可能會導致你在呼叫資料時報錯
  • SET:設定一個指定的自定義例項,官方案例如下
from django.conf import settings
from django.contrib.auth import get_user_model
from django.db import models

def get_sentinel_user():
    return get_user_model().objects.get_or_create(username='deleted')[0]

class MyModel(models.Model):
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.SET(get_sentinel_user),
    )

這個案例的意思是當刪除外來鍵欄位user有關聯時呼叫get_sentinel_user方法,這個方法會返回一個username為deleted的例項

db_constraint: 控制是否在資料庫中為此外來鍵建立約束,預設為True。在資料庫中建立外來鍵約束是資料庫規範中明令禁止的行為,那麼我們可以設定db_constraintFalse從而不在資料庫層面建立約束,但同樣可以使用Django為Foreignkey提供的各種關聯查詢

接下來可以通過如下程式碼將資料庫中的資料轉成ztree所能使用的簡單模式資料並返回

def tree(request):
    mList = Department.objects.all()

    _data = [
        {
            'id': x.id,
            'name': x.name,
            'pId': x.parent.id if x.parent else 0, 'open': 1
        } for x in mList
    ]

    return render(request, 'tree.html', {'data': _data})

注意在前端使用時需要用{{data|safe}}的方式,新增|safe主要是因為Django為了安全預設會對HTML、JS等語法標籤進行轉義,但我們所傳給前端的資料不希望轉義可以通過新增|safe來實現

完整Demo

文章原始碼已上傳至Github,除了以上基礎程式碼外還包含下拉框載入樹等功能,公眾號後臺回覆06獲取原始碼地址吧


相關文章推薦閱讀:

  • 前端外掛之Datatables使用--下篇
  • Django使用Channels實現WebSocket--下篇