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使用scrapy解析js示例
Jan 23 Python
Python标准异常和异常处理详解
Feb 02 Python
python中requests模块的使用方法
Apr 08 Python
python使用wmi模块获取windows下的系统信息 监控系统
Oct 27 Python
编写Python小程序来统计测试脚本的关键字
Mar 12 Python
python中列表和元组的区别
Dec 18 Python
利用Python批量提取Win10锁屏壁纸实战教程
Mar 27 Python
Python数据结构与算法(几种排序)小结
Jun 22 Python
如何分离django中的媒体、静态文件和网页
Nov 12 Python
django xadmin中form_layout添加字段显示方式
Mar 30 Python
DjangoWeb使用Datatable进行后端分页的实现
May 18 Python
Python安装使用Scrapy框架
Apr 12 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中unlink()、mkdir()、rmdir()等方法的使用介绍
2012/12/21 PHP
PHP SPL标准库中的常用函数介绍
2015/05/11 PHP
PHP判断文件是否被引入的方法get_included_files用法示例
2016/11/29 PHP
使用Entrust扩展包在laravel 中实现RBAC的功能
2020/03/16 PHP
JS TextArea字符串长度限制代码集合
2012/10/31 Javascript
输入自动提示搜索提示功能的使用说明:sugggestion.txt
2013/09/02 Javascript
两种方法基于jQuery实现IE浏览器兼容placeholder效果
2014/10/14 Javascript
零基础搭建Node.js、Express、Ejs、Mongodb服务器及应用开发入门
2014/12/20 Javascript
基于jquery实现在线选座订座之影院篇
2015/08/24 Javascript
详解页面滚动值scrollTop在FireFox与Chrome浏览器间的兼容问题
2015/12/03 Javascript
使用JavaScript判断手机浏览器是横屏还是竖屏问题
2016/08/02 Javascript
jQuery实现定位滚动条位置
2016/08/05 Javascript
微信小程序 video详解及简单实例
2017/01/16 Javascript
BootStrap Fileinput上传插件使用实例代码
2017/07/28 Javascript
Vue2.0 组件传值通讯的示例代码
2017/08/01 Javascript
一个基于react的图片裁剪组件示例
2018/04/18 Javascript
JavaScript中 ES6变量的结构赋值
2018/07/10 Javascript
vue新vue-cli3环境配置和模拟json数据的实例
2018/09/19 Javascript
Python实现基于HTTP文件传输实例
2014/11/08 Python
Python实现检测服务器是否可以ping通的2种方法
2015/01/01 Python
在Python中使用cookielib和urllib2配合PyQuery抓取网页信息
2015/04/25 Python
python清除字符串里非数字字符的方法
2015/07/02 Python
pycharm+PyQt5+python最新开发环境配置(踩坑)
2019/02/11 Python
python networkx 包绘制复杂网络关系图的实现
2019/07/10 Python
python实现批量修改文件名
2020/03/23 Python
Django REST framwork的权限验证实例
2020/04/02 Python
如何通过python实现IOU计算代码实例
2020/11/02 Python
一款基于css3的动画按钮代码教程
2014/11/23 HTML / CSS
5分钟让你掌握css3阴影、倒影、渐变小技巧(小编推荐)
2016/08/15 HTML / CSS
CSS3制作轮播图的一种方法
2019/11/11 HTML / CSS
利用纯html5绘制出来的一款非常漂亮的时钟
2015/01/04 HTML / CSS
同学聚会老师邀请函
2014/01/28 职场文书
酒店总经理助理岗位职责
2014/02/01 职场文书
辞职信标准格式
2015/02/27 职场文书
傲慢与偏见电影观后感
2015/06/10 职场文书
python中sqllite插入numpy数组到数据库的实现方法
2021/06/21 Python