無限分類作用不再贅述, 效果如下:
使用方法:
1, 將應(yīng)用拷貝到項目目錄下
2,在項目的setting文件中做兩個設(shè)置
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'll' # 無限分類應(yīng)用 limitless 縮寫 增加此行 ] STATIC_URL = '/static/' STATICFILES_DIRS = [ os.path.join(BASE_DIR,'ll/static') # 加載ll應(yīng)用下的statics目錄 增加這行 ]
3, 在項目的url文件中做如下配置
urlpatterns = [ path('admin/', admin.site.urls), path('ll/',include("ll.urls")) # 增加這行 ]
4, 根據(jù)ll的modles.py中的模型類sorts 到數(shù)據(jù)庫生成表
python manage.py makemigrations ll #生成表對象
python manage.py migrate ll #生成數(shù)據(jù)庫中表
5, 訪問地址:
域名/ll/list
效果如訪問的第一個文件所示
下載文件:
主要文件:
1, 無限分類遞歸查詢
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 # 將開始的父級水平定義為第一級 lev = dic.level #表中級別 if (lev == cls.level): #第一級 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 : 父級id # currentid : 當(dāng)前默認(rèn)選中類別 # top : 是否顯示頂級類別 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">一級分類</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: # 最頂級時使用默認(rèn)設(shè)置值, 否則根據(jù)父級來決定 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>") # 判斷同一個父類下不能有重復(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>") # 獲取原來id的sorthpath及parentid try: row = sorts.objects.get(id=id) except sorts.DoesNotExist: return HttpResponse("<script>alert('id參數(shù)錯誤');history.back();</script>") else: oldParentid = row.parentid oldSortPath = row.sortpath oldLevel = row.level # 獲取現(xiàn)在id的父級的sorthpath nowParentidSortPath = "" if parentid: try: row1 = sorts.objects.values("sortpath", "level").get(id=parentid) except sorts.DoesNotExist: return HttpResponse("<script>alert('父類參數(shù)錯誤');history.back();</script>") else: nowParentidSortPath = row1.get("sortpath") nowLevel = row1.get("level") # 當(dāng)前選擇的父級id的sortpath row.title = title row.orders = orders if parentid == oldParentid: # 父類不變, 直接更新名稱和排序就可以了 row.save() elif oldSortPath in nowParentidSortPath: # 判斷修改類別父類不能為原類別的子類 return HttpResponse("<script>alert('不能選擇自己或子級作為父類');history.back();</script>") elif parentid == 0: # 選擇一級類別 level = 1 sortpath = "0," + str(id) + "," row.level = level row.sortpath = sortpath row.parentid = 0 row.save() chaLevel = oldLevel - level # 更新所有子類的層級 # 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, 無限分類表Sorts模型
from django.db import models # 無限分類表 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) # 從父級第一級開始,每層的id, 包含當(dāng)前id level = models.SmallIntegerField(default=1) # 從父級第一級開始,為第幾級 orders = models.IntegerField(default=1) # 同一級中的排序 pic = models.CharField(default='',blank=True,max_length=200)