無(wú)限分類(lèi)作用不再贅述, 效果如下:

使用方法:
1, 將應(yīng)用拷貝到項(xiàng)目目錄下
2,在項(xiàng)目的setting文件中做兩個(gè)設(shè)置
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'll' # 無(wú)限分類(lèi)應(yīng)用 limitless 縮寫(xiě) 增加此行 ] STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR,'ll/static') # 加載ll應(yīng)用下的statics目錄 增加這行 ]
3, 在項(xiàng)目的url文件中做如下配置
urlpatterns = [
path('admin/', admin.site.urls),
path('ll/',include("ll.urls"))
# 增加這行
]4, 根據(jù)ll的modles.py中的模型類(lèi)sorts 到數(shù)據(jù)庫(kù)生成表
python manage.py makemigrations ll #生成表對(duì)象
python manage.py migrate ll #生成數(shù)據(jù)庫(kù)中表
5, 訪問(wèn)地址:
域名/ll/list
效果如訪問(wèn)的第一個(gè)文件所示
下載文件:
主要文件:
1, 無(wú)限分類(lèi)遞歸查詢(xún)
from .models import sorts
class sortAll:
sortList = []
level = 0
# 查詢(xún)所有子類(lèi)信息
@classmethod
def getChildren(cls, pid=0, space="", rs=[]):
if not rs:
rs = sorts.objects.filter(parentid=pid).order_by("orders")
del cls.sortList[:]
cls.level = 0
# 每次調(diào)用之前,清空列表
if rs:
for dic in rs:
if not cls.level:
cls.level = dic.level
# 將開(kāi)始的父級(jí)水平定義為第一級(jí)
lev = dic.level #表中級(jí)別
if (lev == cls.level): #第一級(jí)
dic.space = ""
elif (lev == cls.level + 1):
space = " |---->"
dic.space = space
else:
dic.space = space
cls.sortList.append(dic)
pid = dic.id
rs = sorts.objects.filter(parentid=pid).order_by("orders")
if rs:
cls.getChildren(pid, " |" + space, rs)
return cls.sortList
@classmethod
# selectName : select 的name屬性值
# pid : 父級(jí)id
# currentid : 當(dāng)前默認(rèn)選中類(lèi)別
# top : 是否顯示頂級(jí)類(lèi)別
def selectTree(cls, pid=0, selectName="parentid", currentid=0, top=False):
lists = cls.getChildren(pid)
strs = '<select name="' + selectName + '">';
if top:
strs += '<option value="0">一級(jí)分類(lèi)</option>'
for row in lists:
if (row.id == currentid):
strs += '<option value="' + str(row.id) + '" selected>' + row.space + row.title + '</option>'
else:
strs += '<option value="' + str(row.id) + '">' + row.space + row.title + '</option>'
strs += '</select>'
return strs
@classmethod
def getParentName(cls, sortpath="", fuhao="->"):
str = ""
if sortpath:
sortpath = sortpath[2:len(sortpath) - 1]
list = sortpath.split(",")
for index in range(len(list)):
row = sorts.objects.get(id=list[index])
if index == 0:
str += row.title
else:
str += fuhao + row.title
return str2, 基于django模型視圖的增刪改操作
from django.shortcuts import render
from django.http import HttpResponse
from .models import sorts
from .sortTree import sortAll
from django.db.models import F,Func,Value
from django.db.models.functions import Replace
def list(request):
list_child = sortAll.getChildren(0)
return render(request, "ll/list.html", {"list_children": list_child})
def add(request):
if request.method == "GET":
currentid = int(request.GET.get("parentid", 0))
dict = {"selectTree":sortAll.selectTree(0,"parentid",currentid,True)}
return render(request,"ll/add.html",dict)
elif request.method == "POST":
post = request.POST
parentid = post.get("parentid",0)
title = post.get("title")
ordders = post.get("orders")
if not title:
return HttpResponse("<script>alert('類(lèi)別名稱(chēng)不能為空');history.back();</script>")
try:
result = sorts.objects.get(parentid=parentid, title=title)
if result:
return HttpResponse("<script>alert('類(lèi)別已經(jīng)存在');history.back();</script>")
except sorts.DoesNotExist:
pass
# 設(shè)置level, sortpath信息begin
level = 1
sortpath = "0,"
if parentid:
# 最頂級(jí)時(shí)使用默認(rèn)設(shè)置值, 否則根據(jù)父級(jí)來(lái)決定
try:
row = sorts.objects.values("level", "sortpath").get(id=parentid)
level = row.get("level") + 1
sortpath = row.get("sortpath")
except sorts.DoesNotExist:
pass
data = {"title":title, "parentid":parentid, "level":level, "sortpath":sortpath, "orders":ordders}
obj = sorts.objects.create(**data)
sortpath = obj.sortpath + str(obj.id) + ","
sorts.objects.filter(id=obj.id).update(sortpath=sortpath)
return HttpResponse("<script>alert('添加成功');location.href='/ll/list/';</script>")
def edit(request):
if request.method == "GET":
id = request.GET.get("id", 0)
try:
row = sorts.objects.get(id=id)
except sorts.DoesNotExist:
return HttpResponse("<script>alert('傳遞參數(shù)不正確, 找不到數(shù)據(jù)');history.back();</script>")
else:
selectTree = sortAll.selectTree(pid=0, selectName='parentid', currentid=row.parentid, top=True)
return render(request, "ll/edit.html", {"row": row, "selectTree": selectTree})
elif request.method == "POST":
id = int(request.POST.get("id"))
parentid = int(request.POST.get("parentid"))
title = request.POST.get("title")
orders = request.POST.get("orders")
if not title:
return HttpResponse("<script>alert('名稱(chēng)不能為空');history.back();</script>")
# 判斷同一個(gè)父類(lèi)下不能有重復(fù)的名稱(chēng)
try:
rs = sorts.objects.exclude(id=id).get(parentid=parentid, title=title)
except sorts.DoesNotExist:
pass
else:
return HttpResponse("<script>alert('名稱(chēng)重復(fù)');history.back();</script>")
# 獲取原來(lái)id的sorthpath及parentid
try:
row = sorts.objects.get(id=id)
except sorts.DoesNotExist:
return HttpResponse("<script>alert('id參數(shù)錯(cuò)誤');history.back();</script>")
else:
oldParentid = row.parentid
oldSortPath = row.sortpath
oldLevel = row.level
# 獲取現(xiàn)在id的父級(jí)的sorthpath
nowParentidSortPath = ""
if parentid:
try:
row1 = sorts.objects.values("sortpath", "level").get(id=parentid)
except sorts.DoesNotExist:
return HttpResponse("<script>alert('父類(lèi)參數(shù)錯(cuò)誤');history.back();</script>")
else:
nowParentidSortPath = row1.get("sortpath")
nowLevel = row1.get("level")
# 當(dāng)前選擇的父級(jí)id的sortpath
row.title = title
row.orders = orders
if parentid == oldParentid:
# 父類(lèi)不變, 直接更新名稱(chēng)和排序就可以了
row.save()
elif oldSortPath in nowParentidSortPath:
# 判斷修改類(lèi)別父類(lèi)不能為原類(lèi)別的子類(lèi)
return HttpResponse("<script>alert('不能選擇自己或子級(jí)作為父類(lèi)');history.back();</script>")
elif parentid == 0:
# 選擇一級(jí)類(lèi)別
level = 1
sortpath = "0," + str(id) + ","
row.level = level
row.sortpath = sortpath
row.parentid = 0
row.save()
chaLevel = oldLevel - level
# 更新所有子類(lèi)的層級(jí)
# sorts.objects.exclude(id=id).filter(sortpath__icontains=oldSortPath).
# update(sortpath=Func(F('sortpath'), Value(oldSortPath), Value(sortpath), function='replace',),level = F("level") - chaLevel)
sorts.objects.exclude(id=id).filter(sortpath__icontains=oldSortPath).update(
sortpath=Replace('sortpath', Value(oldSortPath), Value(sortpath)),
level=F("level") - chaLevel
)
else:
sortpath = nowParentidSortPath + str(id) + ","
level = nowLevel + 1
chaLevel = oldLevel - level
row.sortpath = sortpath
row.level = level
row.parentid = parentid
row.save()
sorts.objects.exclude(id=id).filter(sortpath__icontains=oldSortPath).update(
sortpath=Replace('sortpath', Value(oldSortPath), Value(sortpath)),
level=F("level") - chaLevel
)
return HttpResponse("<script>alert('修改成功');location.href='/ll/list/';</script>")
def delete(request):
id = request.GET.get("id", 0)
sorts.objects.filter(sortpath__icontains=str(id) + ",").delete()
return HttpResponse("<script>alert('刪除成功');location.href='/ll/list';</script>")4, 無(wú)限分類(lèi)表Sorts模型
from django.db import models # 無(wú)限分類(lèi)表 class sorts(models.Model): title = models.CharField(max_length=100) # 類(lèi)別名稱(chēng) parentid = models.IntegerField(default=0) # 類(lèi)別的 父 id sortpath = models.CharField(default='',blank=True,max_length=200) # 從父級(jí)第一級(jí)開(kāi)始,每層的id, 包含當(dāng)前id level = models.SmallIntegerField(default=1) # 從父級(jí)第一級(jí)開(kāi)始,為第幾級(jí) orders = models.IntegerField(default=1) # 同一級(jí)中的排序 pic = models.CharField(default='',blank=True,max_length=200)
