![django多级联动效果预览]()
类似 国家 -> 省 -> 市 这样的多级分类联动下拉列表在各种项目中都经常用到,但是放狗搜了半天也没有一套Django完整的解决教程,最接近的是 芝麻问答 ,但也只是在模型上简单描述了思路,离最终的完成还有一段距离。所以,只有自己动手了…
思路:
普通Html页面下多级联动的实现是通过对<OPTION>进行动作绑定,一旦发生数据改变就对子类别的下拉列表进行更新。Django于此相异的地方主要在于后台数据的传递,我们只要建立一个分类数据读取接口,然后将从数据库中读出的相关值生成JSON格式传递到前台页面即可。
在数据库的设计上,我想尽量简单,只是用三个字段来实现无线分类,分别是id,name,pid(父级分类ID);另外由于分类并非经常更改,但要经常读取,为了避免不必要的数据库开销,我将每次更新后的分类数据生成一个静态JS格式文件供前台读取。
实现代码:
首先是选择前台页面的JS联动代码,感谢“YAODAYIZI”提供的脚本,具体如下:
1.表现层Html页面(category_list.html):
05 | Django Learning 下拉列表多级联动选择 |
07 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
08 | <script language="javascript"> |
09 | function Dlist(array) { |
13 | this.subSelectChange = function(selectName1, selectName2) { |
14 | var obj1 = document.all[selectName1]; |
15 | var obj2 = document.all[selectName2]; |
16 | var objName = this.toString(); |
18 | obj1.onchange = function() { |
19 | me.optionChange(this.options[this.selectedIndex].value, obj2.id) |
22 | this.firstSelectChange = function(indexName, selectName) { |
23 | this.obj = document.all[selectName]; |
24 | this.indexName = indexName; |
25 | this.optionChange(this.indexName, this.obj.id) |
27 | this.optionChange = function(indexName, selectName) { |
28 | var obj1 = document.all[selectName]; |
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]) |
43 | <a href="?mode=reset"> |
46 | <form name="form1" method="post"> |
47 | <SELECT ID="s1" NAME="s1" size="10"> |
51 | <SELECT ID="s2" NAME="s2" size="10"> |
55 | <SELECT ID="s3" NAME="s3" size="10"> |
60 | <script type="text/javascript" src="/static/js/category_data.js"><!-- 此处根据你的category_data.js存放位置进行更改--> |
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"); |
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) |
7 | return (u'%d,%d,%s') % (self.id,self.c_father,self.c_name) |
3. 根据数据库生成的JS数据文件(category_data.js):
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>
02 | def category_manage(request): |
03 | if request.GET.has_key('mode'): |
04 | mode = request.GET['mode'] |
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() |
10 | jfile.write ("array[%d]=new Array('%d','%d','%s')\n"%(c.id-1,c.id,c.c_father,c.c_name)) |
12 | return render_to_response('category.html',locals()) |
到这里已经完成的七七八八了,然后去url.py下配置好相关路径就可以运行了,如果你希望直接从数据库中读取或者希望和Form类紧密关联,修改起来也会比较容易,有时间的话下次我再另外发一篇练习文章。
希望以上的内容对你有所帮助。