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将多份excel表格整理成一份表格
Jan 03 Python
python3安装pip3(install pip3 for python 3.x)
Apr 03 Python
使用python根据端口号关闭进程的方法
Nov 06 Python
Django组件之cookie与session的使用方法
Jan 10 Python
python set内置函数的具体使用
Jul 02 Python
详解Python3 pickle模块用法
Sep 16 Python
Python3 pandas 操作列表实例详解
Sep 23 Python
什么是Python中的顺序表
Jun 02 Python
python操作微信自动发消息的实现(微信聊天机器人)
Jul 14 Python
用pandas划分数据集实现训练集和测试集
Jul 20 Python
Python通过getattr函数获取对象的属性值
Oct 16 Python
Python 制作查询商品历史价格的小工具
Oct 20 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
ThinkPHP和UCenter接口冲突的解决方法
2016/07/25 PHP
PHP环境搭建(php+Apache+mysql)
2016/11/14 PHP
PHP处理Ajax请求与Ajax跨域问题
2017/02/13 PHP
thinkPHP5框架自定义验证器实现方法分析
2018/06/11 PHP
PHP获取访问设备信息的方法示例
2019/02/20 PHP
PHP pthreads v3使用中的一些坑和注意点分析
2020/02/21 PHP
Exitjs获取DataView中图片文件名
2009/11/26 Javascript
js展开闭合效果演示代码
2013/07/24 Javascript
JS下拉缓冲菜单示例代码
2013/08/30 Javascript
浅析JavaScript基本类型与引用类型
2014/05/28 Javascript
jQuery的animate函数学习记录
2014/08/08 Javascript
JS实现让访问者自助选择网页文字颜色的方法
2015/02/24 Javascript
JavaScript常用脚本汇总(三)
2015/03/04 Javascript
详解JavaScript的Date对象(制作简易钟表)
2020/04/07 Javascript
基于JavaScript实现动态创建表格和增加表格行数
2015/12/20 Javascript
javascript+css3 实现动态按钮菜单特效
2016/02/06 Javascript
jQuery移动端图片上传组件
2016/06/12 Javascript
Vue.js 动态为img的src赋值方法
2018/03/14 Javascript
puppeteer库入门初探
2019/01/09 Javascript
React传值 组件传值 之间的关系详解
2019/08/26 Javascript
微信小程序实现左滑删除效果
2020/11/18 Javascript
Python实现一个简单的MySQL类
2015/01/07 Python
Python使用scrapy采集数据过程中放回下载过大页面的方法
2015/04/08 Python
Python在Console下显示文本进度条的方法
2016/02/14 Python
利用python实现在微信群刷屏的方法
2019/02/21 Python
Python字符串中删除特定字符的方法
2020/01/15 Python
Oroton中国官网:澳洲知名奢侈配饰品牌
2017/03/26 全球购物
澳大利亚家具和家居用品购物网站:Zanui
2018/12/29 全球购物
FC-Moto英国:欧洲最大的摩托车服装和头盔商店之一
2019/08/25 全球购物
局域网标准
2016/09/10 面试题
护理专业个人求职简历的自我评价
2013/10/13 职场文书
晚归检讨书
2014/02/19 职场文书
库房保管员岗位职责
2014/04/07 职场文书
新闻传播专业求职信
2014/07/22 职场文书
Pytorch GPU内存占用很高,但是利用率很低如何解决
2021/06/01 Python
Android开发 使用文件储存的方式保存QQ密码
2022/04/24 Java/Android