一、数据库设计
对于多级目录的设计,最简单直接的方式,可以直接把目录的名称和内容等相关信息放到一个表里,如何区分顶级目录和子目录是设计的关键。
思想:
可以把目录树看作是一个具有多个根节点的树状结构,子目录就是儿子,父目录就是父节点,每个子目录只能有一个父节点。 因此可以在设计时,设置顶级目录的parent_id为null, 在查询的时候可以直接根据null来查询出所有的顶级目录, 怎么去添加子节点,每个子目录的都有一个parent_id,parent_id的值对应其他记录的id, 这样就可以通过parent_id和id 来形成一个树。获取到根节点后,再遍历每个根节点的叶子节点,如果有叶子节点,那么就挂在它底下,类如id为5的对象的parent_id为1,那么就把data挂在id未1的记录下,id为20的记录的Parent_id为5,那么就把id为20的记录挂在id为5的记录下,json结构如下:
{
"id": 1,
"text": "顶级目录",
"parent_menu_tree_item": null,
"menu_type": 0,
"data": [
{
"id": 5,
"text": "二级目录",
"parent_menu_tree_item": 1,
"menu_type": 0,
"data": {
"id": 20,
"text": "三级目录",
"parent_menu_tree_item": 5,
"menu_type": 0
}
}
]
}
二、程序设计
思想: 递归。 先select出所有parent_id为null的记录,即根节点,然后遍历每一个父亲的子树,如果有子树,那么就继续递归遍历所有的子树,每遍历一次就挂在父节点的i["data"]上,遍历完了就下一个根节点。
核心代码如下:
1) 获取到所有的根节点:
items = HandsOnCaseMenuTreeItem.objects.using("admin").filter(parent_menu_tree_item=None,
resource_id=resource_id) \
.values("id", "text", "parent_menu_tree_item", "menu_type")
datas = []
for i in items:
find_child(i, datas, resource_id)
r.data = datas
2) 递归遍历所有根节点:
def find_child(i, datas):
p_id = i["id"]
p = HandsOnCaseMenuTreeItem.objects \
.filter(parent_menu_tree_item=p_id) \
.values("id", "text", "parent_menu_tree_item", "menu_type")
if len(p) > 1:
i['data'] = list(p)
datas.append(i)
for j in p:
find_child(j, datas)
elif len(p) == 1:
find_child(p[0], datas)
i["data"] = p[0]
return datas