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 相关文章推荐
PyQt5每天必学之弹出消息框
Apr 19 Python
Python实现的质因式分解算法示例
May 03 Python
使用python验证代理ip是否可用的实现方法
Jul 25 Python
如何使用Python实现自动化水军评论
Jun 26 Python
Python3 执行系统命令并获取实时回显功能
Jul 09 Python
python中将两组数据放在一起按照某一固定顺序shuffle的实例
Jul 15 Python
详解python实现数据归一化处理的方式:(0,1)标准化
Jul 17 Python
python爬虫 模拟登录人人网过程解析
Jul 31 Python
Python 中使用 PyMySQL模块操作数据库的方法
Nov 10 Python
Python通过4种方式实现进程数据通信
Mar 12 Python
解决Keras的自定义lambda层去reshape张量时model保存出错问题
Jul 01 Python
Python hashlib模块的使用示例
Oct 09 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
php数据库密码的找回的步骤
2011/01/12 PHP
解析php中eclipse 用空格替换 tab键
2013/06/24 PHP
PHP以指定字段为索引返回数据库所取的数据数组
2013/06/30 PHP
php防止sql注入之过滤分页参数实例
2014/11/03 PHP
PHP框架Laravel插件Pagination实现自定义分页
2020/04/22 PHP
PHP大文件分块上传功能实例详解
2019/07/22 PHP
前端开发的开始---基于面向对象的Ajax类
2010/09/17 Javascript
两个Javascript小tip资料
2010/11/23 Javascript
检测jQuery.js是否已加载的判断代码
2011/05/20 Javascript
JavaScript高级程序设计 阅读笔记(十八) js跨平台的事件
2012/08/14 Javascript
网页整体变灰白色(兼容各浏览器)实例
2013/04/21 Javascript
JQuery文字列表向上滚动的代码
2013/11/13 Javascript
JS取request值以及自动执行使用示例
2014/02/24 Javascript
jQuery显示和隐藏 常用的状态判断方法
2015/01/29 Javascript
js模拟淘宝网的多级选择菜单实现方法
2015/08/18 Javascript
Vue.js实现简单ToDoList 前期准备(一)
2016/12/01 Javascript
详解基于angular路由的requireJs按需加载js
2017/01/20 Javascript
JavaScript获取tr td 的三种方式全面总结(推荐)
2017/08/15 Javascript
angularjs中$http异步上传Excel文件方法
2018/02/23 Javascript
在vue里面设置全局变量或数据的方法
2018/03/09 Javascript
React Router v4 入坑指南(小结)
2018/04/08 Javascript
微信小程序实现折叠与展开文章功能
2018/06/12 Javascript
在vue中使用echarts图表实例代码详解
2018/10/22 Javascript
vue添加class样式实例讲解
2019/02/12 Javascript
vue写h5页面的方法总结
2019/02/12 Javascript
vue+高德地图写地图选址组件的方法
2019/05/18 Javascript
解决axios post 后端无法接收数据的问题
2019/10/29 Javascript
python 文件与目录操作
2008/12/24 Python
python脚本实现查找webshell的方法
2014/07/31 Python
Python实现TCP/IP协议下的端口转发及重定向示例
2016/06/14 Python
新西兰最大的连锁超市:Countdown
2020/06/04 全球购物
教师个人自我评价范文
2014/04/13 职场文书
服务行业口号
2014/06/11 职场文书
2014年高校辅导员工作总结
2014/12/09 职场文书
MySQL系列之六 用户与授权
2021/07/02 MySQL
MySQL脏读,幻读和不可重复读
2022/05/11 MySQL