django admin 后台实现三级联动的示例代码


Posted in Python onJune 22, 2018

在刚进公司的时候,要写一个需求,使用django的admin站点管理,实现一个二级联动的功能,因为要用到django自带的页面,因为不是自定义的,不能直接添加js代码。根据我自己的研究简单的记录一下大概步骤。

项目创建流程略过,这里使用MySQL数据库和py3为例。

示例项目大概功能,添加一个人物信息,地区通过三级联动选择。

一、项目创建成功后,首先写模型类代码:

class AreaInfo(models.Model):
  """地区模型类"""

  name = models.CharField(max_length = 50)
  pid = models.ForeignKey('self', related_name = 'areas',null=True, blank=True, on_delete = models.SET_NULL)
  
  def __str__(self):
    return self.name
    
  class Meta:
    db_table = 'areainfo'
    
    verbose_name = '地区信息'
    verbose_name_plural = verbose_name
    

class HeroInfo(models.Model):
  """任务信息模型类"""
  
  name = models.CharField(max_length = 50)
  # on_delete 表示关联的外键表删除数据时,该条数据不变,外键置为空
  province = models.ForeignKey(AreaInfo, null=True, blank=True, on_delete = models.SET_NULL)
  city = models.ForeignKey(AreaInfo, related_name = 'areainfo', null=True, blank=True, on_delete = models.SET_NULL)
  country = models.ForeignKey(AreaInfo, related_name = 'areainfos', null=True, blank=True, on_delete = models.SET_NULL)
  
  def __str__(self):
    return self.name
  
  class Meta:
    db_table = 'heroinfo'
    
    verbose_name = '人物信息'
    verbose_name_plural = verbose_name

在一个模型类中,两个外键关联同一个模型类,要使用related_name进行设置,否则会报错。related_name 不能相同,否则迁移数据库会出错,反向查询名称重复。

然后进行数据库迁移,在数据库中导入地区信息,为后续使用做准备。

使用数据库时,不要忘记在settings.py中修改数据库配置。同时使用时,要在应用的__init__.py文件中,添加以下两行代码:

import pymysql
pymysql.install_as_MySQLdb

因为在MySQLdb是python连接MySQL的模块,在py2中使用,py3中没有MySQLdb,所以py3要安装pymysql,并进行以上设置。

二、以上步骤完成之后进行第二部,注册模型类

@admin.register(AreaInfo)
class AreaAdmin(admin.ModelAdmin):
  
  list_display = ('name', 'pid') # 这里要使用元组或者列表

@admin.register(HeroInfo)
class HeroAdmin(admin.ModelAdmin):
  
  list_display = ('name', 'province', 'city', 'country')

  change_form_template = 'area.html'

在这里用到了change_form_template,可以自定义访问路径,改变django默认的路径

三、在template中新建一个文件admin,在admin中新建一个area.html页面,将django 中的 change_form.html内容拷贝过来。

后面写三级联动的js要在这里,改变django默认的路径,读取的也是该页面,上面在admin中已经进行了设置。

四、以上步骤完成以后就可以开始写三级联动的js和view。

1.html中添加js代码如下:

发送ajax请求,获取并展示省份信息

$.get('/areas/choose/province/',function(p_info){
  var province_info = $('#id_province').empty().append('<option value>'+'---------'+'</option>');
  
  $.each(p_info.p_lists,function(i,province){
    
  province_info.append('<option value="'+province.p_id+'">'+province.p_name+'</option>')
          
  });

url配置: url(r'^choose/province/$', views.choose_province),

视图代码:

def choose_province(request):
  """查询省"""

  provinces = AreaInfo.objects.filter(pid=None)


  p_lists = [{"p_id": province.id, "p_name": province.name} for province in provinces]
  p_info = {"p_lists":p_lists}
  
  return JsonResponse(p_info, safe=False)

这里注意,要设置safe=False,否则会报错:

TypeError: In order to allow non-dict objects to be serialized set the safe parameter to False.

2.发送ajax请求,获取并展示城市信息

$.get('/areas/choose/province/',function(p_info){
    var province_info = $('#id_province').empty().append('<option value>'+'---------'+'</option>');
    
    $.each(p_info.p_lists,function(i,province){
      
    province_info.append('<option value="'+province.p_id+'">'+province.p_name+'</option>')
      
  });

    $('#id_province').change(function(){
      p_id = $(this).val();
      
  $.get('/areas/choose/city/',{'p_id':p_id},function(c_info){
      var city_info = $('#id_city').empty().append('<option value>'+'---------'+'</option>');
      $.each(c_info.c_lists,function(i,city){
        city_info.append('<option value="'+city.c_id+'">'+city.c_name+'</option>')
        })
      })
    });

URL配置:url(r'^choose/city/$', views.choose_city),

视图代码:

def choose_city(request):
  """查询市"""

  p_id = request.GET.get('p_id')
  print(p_id,'--------')
  citys = AreaInfo.objects.filter(pid=p_id)
  c_lists = [{"c_id": city.id, "c_name": city.name} for city in citys]
  print(c_lists[0:5])
  c_info = {"c_lists": c_lists}
  return JsonResponse(c_info, safe=False)

3.发送ajax请求,获取并展示区信息
$.get('/areas/choose/province/',function(p_info){
    var province_info = $('#id_province').empty().append('<option value>'+'---------'+'</option>');
    
    $.each(p_info.p_lists,function(i,province){
      
    province_info.append('<option value="'+province.p_id+'">'+province.p_name+'</option>')
      
  });

    $('#id_province').change(function(){
      p_id = $(this).val();
      
  $.get('/areas/choose/city/',{'p_id':p_id},function(c_info){
      var city_info = $('#id_city').empty().append('<option value>'+'---------'+'</option>');
      $.each(c_info.c_lists,function(i,city){
        city_info.append('<option value="'+city.c_id+'">'+city.c_name+'</option>')
        })
      })
    });  
    
  $('#id_city').change(function(){
    c_id = $(this).val();

  $.get('/areas/choose/area/',{"c_id": c_id},function(a_info){
    var area_info = $('#id_country').empty().append('<option value>'+'---------'+'</option>');
      $.each(a_info.a_lists,function(i,area){
        area_info.append('<option value="'+area.a_id+'">'+area.a_name+'</option>')
        });
      });
    });
            });

URL配置:url(r'^choose/area/$', views.choose_area),

视图代码:

def choose_area(request):
  """查询区"""
  
  c_id = request.GET.get('c_id')
  print(c_id,'=======')
  areas = AreaInfo.objects.filter(pid=c_id)
  print(areas)
  a_lists = [{"a_id": area.id, "a_name": area.name } for area in areas]
  a_info = {"a_lists": a_lists}
  print(a_info)
  return JsonResponse(a_info, safe=False)

五、完成之后便可实现admin后台站点的三级联动

六、django功能强大,用法很多,平时没事多研究官方文档

七、完整代码在我的github上可以看到

https://github.com/duyunj/ThirdRepository

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python 'takes exactly 1 argument (2 given)' Python error
Dec 13 Python
python 与GO中操作slice,list的方式实例代码
Mar 20 Python
Python AES加密模块用法分析
May 22 Python
python绘制双柱形图代码实例
Dec 14 Python
Python实现快速傅里叶变换的方法(FFT)
Jul 21 Python
对python PLT中的image和skimage处理图片方法详解
Jan 10 Python
使用python itchat包爬取微信好友头像形成矩形头像集的方法
Feb 21 Python
一步步教你用python的scrapy编写一个爬虫
Apr 17 Python
Python OpenCV利用笔记本摄像头实现人脸检测
Aug 20 Python
Python Django Vue 项目创建过程详解
Jul 29 Python
Django文件上传与下载(FileFlid)
Oct 06 Python
Python使用pickle进行序列化和反序列化的示例代码
Sep 22 Python
python使用turtle库与random库绘制雪花
Jun 22 #Python
Python3导入CSV文件的实例(跟Python2有些许的不同)
Jun 22 #Python
Django Admin实现三级联动的示例代码(省市区)
Jun 22 #Python
详解python中的json和字典dict
Jun 22 #Python
python实现雨滴下落到地面效果
Jun 21 #Python
使用python读取csv文件快速插入数据库的实例
Jun 21 #Python
详解python3中tkinter知识点
Jun 21 #Python
You might like
一个改进的UBB类
2006/10/09 PHP
PHP高手需要要掌握的知识点
2014/08/21 PHP
PHP转盘抽奖接口实例
2015/02/09 PHP
php生成高清缩略图实例详解
2015/12/07 PHP
ie和firefox中img对象区别的困惑
2006/12/27 Javascript
JS是否可以跨文件同时控制多个iframe页面的应用技巧
2007/12/16 Javascript
Jquery中的CheckBox、RadioButton、DropDownList的取值赋值实现代码
2011/10/12 Javascript
jquery实现简单易懂的图片展示小例子
2013/11/21 Javascript
jQuery判断元素是否存在的可靠方法
2014/05/06 Javascript
javascript实现base64 md5 sha1 密码加密
2015/09/09 Javascript
总结JavaScript中布尔操作符||与&amp;&amp;的使用技巧
2015/11/17 Javascript
Linux下为Node.js程序配置MySQL或Oracle数据库的方法
2016/03/19 Javascript
常用Javascript函数与原型功能收藏(必看篇)
2016/10/09 Javascript
通过修改360抢票的刷新频率和突破8车次限制实现方法
2017/01/04 Javascript
使用jQuery.Pin垂直滚动时固定导航
2017/05/24 jQuery
AngularJS解决ng-if中的ng-model值无效的问题
2017/06/21 Javascript
Angularjs自定义指令实现分页插件(DEMO)
2017/09/16 Javascript
javascript 产生随机数的几种方法总结
2017/09/26 Javascript
Vue 莹石摄像头直播视频实例代码
2018/08/31 Javascript
inquirer.js一个用户与命令行交互的工具详解
2019/05/18 Javascript
ES6 Promise对象的含义和基本用法分析
2019/06/14 Javascript
vue本地打开build后生成的dist文件夹index.html问题
2019/09/04 Javascript
javascript运行机制之执行顺序理解
2020/08/03 Javascript
python生成lmdb格式的文件实例
2018/11/08 Python
python使用Pandas库提升项目的运行速度过程详解
2019/07/12 Python
python sqlite的Row对象操作示例
2019/09/11 Python
pymysql的简单封装代码实例
2020/01/08 Python
keras中模型训练class_weight,sample_weight区别说明
2020/05/23 Python
matplotlib教程——强大的python作图工具库
2020/10/15 Python
css3 中translate和transition的使用方法
2020/03/26 HTML / CSS
Antler英国官网:购买安特丽行李箱、拉杆箱
2019/08/25 全球购物
班组长安全职责
2014/01/05 职场文书
教师节班会主持词
2015/07/06 职场文书
2016年党建工作简报
2015/11/26 职场文书
读《解忧杂货店》有感:请相信一切都是最好的安排
2019/11/07 职场文书
导游词之西递宏村
2019/12/10 职场文书