zoukankan      html  css  js  c++  java
  • Django下三级/多级联动的解决办法

    最终实现效果:

    类似  国家 -> 省 -> 市 这样的多级分类联动下拉列表在各种项目中都经常用到,但是放狗搜了半天也没有一套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 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类紧密关联,修改起来也会比较容易,有时间的话下次我再另外发一篇练习文章。
    希望以上的内容对你有所帮助。

  • 相关阅读:
    iOS IM开发建议(三)添加一个自定义键盘
    iOS IM开发建议(二)计算TableViewCell的高度:图文混排
    iOS IM开发建议(一)App框架设计
    iOS IM开发准备工作(五)iOS中的struct怎么处理
    关东升的iOS实战系列图书 《iOS实战:入门与提高卷(Swift版)》已经上市
    关东升的《从零开始学Swift》3月9日已经上架
    《从零开始学Swift》学习笔记(Day 71)——Swift与C/C++混合编程之数据类型映射
    《从零开始学Swift》学习笔记(Day 70)——Swift与Objective-C混合编程之Swift与Objective-C API映射
    《从零开始学Swift》学习笔记(Day 69)——Swift与Objective-C混合编程之语言
    《从零开始学Swift》学习笔记(Day 10)——运算符是“ +、-、*、/ ”吗?
  • 原文地址:https://www.cnblogs.com/lddhbu/p/2603946.html
Copyright © 2011-2022 走看看