無(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 str
2, 基于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)