最終實現效果:

類似 國家 -> 省 -> 市 這樣的多級分類聯動下拉列表在各種項目中都經常用到,但是放狗搜了半天也沒有一套Django完整的解決教程,最接近的是 芝麻問答 ,但也只是在模型上簡單描述了思路,離最終的完成還有一段距離。所以,只有自己動手了…
思路:
普通Html頁面下多級聯動的實現是通過對<OPTION>進行動作綁定,一旦發生數據改變就對子類別的下拉列表進行更新。Django於此相異的地方主要在於后台數據的傳遞,我們只要建立一個分類數據讀取接口,然后將從數據庫中讀出的相關值生成JSON格式傳遞到前台頁面即可。
在數據庫的設計上,我想盡量簡單,只是用三個字段來實現無線分類,分別是id,name,pid(父級分類ID);另外由於分類並非經常更改,但要經常讀取,為了避免不必要的數據庫開銷,我將每次更新后的分類數據生成一個靜態JS格式文件供前台讀取。
實現代碼:
首先是選擇前台頁面的JS聯動代碼,感謝“YAODAYIZI”提供的腳本,具體如下:
1.表現層Html頁面(category_list.html):
01 |
<!DOCTYPE HTML PUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"> |
02 |
<html> |
03 |
<head> |
04 |
<title> |
05 |
Django Learning 下拉列表多級聯動選擇 |
06 |
</title> |
07 |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
08 |
<script language="javascript"> |
09 |
function Dlist(array) { |
10 |
this.array = array; |
11 |
this.indexName = ''; |
12 |
this.obj = ''; |
13 |
this.subSelectChange = function(selectName1, selectName2) { |
14 |
var obj1 = document.all[selectName1]; |
15 |
var obj2 = document.all[selectName2]; |
16 |
var objName = this.toString(); |
17 |
var me = this; |
18 |
obj1.onchange = function() { |
19 |
me.optionChange(this.options[this.selectedIndex].value, obj2.id) |
20 |
} |
21 |
} |
22 |
this.firstSelectChange = function(indexName, selectName) { |
23 |
this.obj = document.all[selectName]; |
24 |
this.indexName = indexName; |
25 |
this.optionChange(this.indexName, this.obj.id) |
26 |
} |
27 |
this.optionChange = function(indexName, selectName) { |
28 |
var obj1 = document.all[selectName]; |
29 |
var me = this; |
30 |
obj1.length = 0; |
31 |
obj1.options[0] = new Option("請選擇", ''); |
32 |
for (var i = 0; i < this.array.length; i++) { |
33 |
if (this.array[i][1] == indexName) { |
34 |
obj1.options[obj1.length] = new Option(this.array[i][2], this.array[i][0]) |
35 |
} |
36 |
} |
37 |
} |
38 |
} |
39 |
</script> |
40 |
</head> |
41 |
42 |
<body> |
43 |
<a href="?mode=reset"> |
44 |
重建靜態文件 |
45 |
</a> |
46 |
<form name="form1" method="post"> |
47 |
<SELECT ID="s1" NAME="s1" size="10"> |
48 |
<OPTION selected> |
49 |
</OPTION> |
50 |
</SELECT> |
51 |
<SELECT ID="s2" NAME="s2" size="10"> |
52 |
<OPTION selected> |
53 |
</OPTION> |
54 |
</SELECT> |
55 |
<SELECT ID="s3" NAME="s3" size="10"> |
56 |
<OPTION selected> |
57 |
</OPTION> |
58 |
</SELECT> |
59 |
</form> |
60 |
<script type="text/javascript" src="/static/js/category_data.js"><!-- 此處根據你的category_data.js存放位置進行更改--> |
61 |
</script> |
62 |
<script type="text/javascript"> |
63 |
var liandong = new Dlist(array) liandong.firstSelectChange("0", "s1");<!-- 聯動關系設置--> |
64 |
liandong.subSelectChange("s1", "s2"); |
65 |
liandong.subSelectChange("s2", "s3"); |
66 |
</script> |
67 |
<hr> |
68 |
<div> |
69 |
Thanks for visiting. |
70 |
</div> |
71 |
</body> |
72 |
</html> |
2.Model類
1 |
class Category(models.Model): |
2 |
c_name = models.CharField(max_length=20,help_text="類別名稱") |
3 |
c_father = models.IntegerField(max_length=4,default=0,help_text="父級類別ID") |
4 |
c_hidden = models.BooleanField(default=0,blank=True) |
5 |
6 |
def __unicode__(self): |
7 |
return (u'%d,%d,%s') % (self.id,self.c_father,self.c_name) |
3. 根據數據庫生成的JS數據文件(category_data.js):
01 |
var array=new Array(); |
02 |
array[0]=new Array('1','0','羅萊') //id,pid,name |
03 |
array[1]=new Array('2','0','優家') |
04 |
array[2]=new Array('3','0','寶縵') |
05 |
array[3]=new Array('4','0','其他') |
06 |
array[4]=new Array('5','1','芯類') |
07 |
array[5]=new Array('6','1','家居類') |
08 |
array[6]=new Array('7','5','被芯') |
09 |
array[7]=new Array('8','5','枕芯') |
10 |
array[8]=new Array('9','2','新經典') |
11 |
array[9]=new Array('10','2','新優雅') |
4. 根據數據庫生成的category_data的辦法(view.py):< /strong>
01 |
import codecs |
02 |
def category_manage(request): |
03 |
if request.GET.has_key('mode'): |
04 |
mode = request.GET['mode'] |
05 |
if mode == 'reset': |
06 |
jfile = codecs.open('static/js/category_data.js','w','utf-8')#Python3.0以上版本可以直接使用f.open(...,'encoding':'utf-8') |
07 |
jfile.write("var array=new Array();\n") |
08 |
clist = Category.objects.all() |
09 |
for c in clist: |
10 |
jfile.write ("array[%d]=new Array('%d','%d','%s')\n"%(c.id-1,c.id,c.c_father,c.c_name)) |
11 |
jfile.close() |
12 |
return render_to_response('category.html',locals()) |
到這里已經完成的七七八八了,然后去url.py下配置好相關路徑就可以運行了,如果你希望直接從數據庫中讀取或者希望和Form類緊密關聯,修改起來也會比較容易,有時間的話下次我再另外發一篇練習文章。
希望以上的內容對你有所幫助。
