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

使用方法:
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ú)限分類應(yīng)用 limitless 縮寫 增加此行 ] 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中的模型類sorts 到數(shù)據(jù)庫(kù)生成表
python manage.py makemigrations ll #生成表對(duì)象
python manage.py migrate ll #生成數(shù)據(jù)庫(kù)中表
5, 訪問地址:
域名/ll/list
效果如訪問的第一個(gè)文件所示
下載文件:
主要文件:
1, 無(wú)限分類遞歸查詢
from .models import sorts
class sortAll:
sortList = []
level = 0
# 查詢所有子類信息
@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
# 將開始的父級(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)選中類別
# top : 是否顯示頂級(jí)類別
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í)分類</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('類別名稱不能為空');history.back();</script>")
try:
result = sorts.objects.get(parentid=parentid, title=title)
if result:
return HttpResponse("<script>alert('類別已經(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('名稱不能為空');history.back();</script>")
# 判斷同一個(gè)父類下不能有重復(fù)的名稱
try:
rs = sorts.objects.exclude(id=id).get(parentid=parentid, title=title)
except sorts.DoesNotExist:
pass
else:
return HttpResponse("<script>alert('名稱重復(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('父類參數(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:
# 父類不變, 直接更新名稱和排序就可以了
row.save()
elif oldSortPath in nowParentidSortPath:
# 判斷修改類別父類不能為原類別的子類
return HttpResponse("<script>alert('不能選擇自己或子級(jí)作為父類');history.back();</script>")
elif parentid == 0:
# 選擇一級(jí)類別
level = 1
sortpath = "0," + str(id) + ","
row.level = level
row.sortpath = sortpath
row.parentid = 0
row.save()
chaLevel = oldLevel - level
# 更新所有子類的層級(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ú)限分類表Sorts模型
from django.db import models # 無(wú)限分類表 class sorts(models.Model): title = models.CharField(max_length=100) # 類別名稱 parentid = models.IntegerField(default=0) # 類別的 父 id sortpath = models.CharField(default='',blank=True,max_length=200) # 從父級(jí)第一級(jí)開始,每層的id, 包含當(dāng)前id level = models.SmallIntegerField(default=1) # 從父級(jí)第一級(jí)開始,為第幾級(jí) orders = models.IntegerField(default=1) # 同一級(jí)中的排序 pic = models.CharField(default='',blank=True,max_length=200)
