最終實現效果:
類似 國家 -> 省 -> 市 這樣的多級分類聯動下拉列表在各種項目中都經常用到,但是放狗搜了半天也沒有一套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類緊密關聯,修改起來也會比較容易,有時間的話下次我再另外發一篇練習文章。
希望以上的內容對你有所幫助。