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实现的希尔排序算法实例
Jul 01 Python
Python中atexit模块的基本使用示例
Jul 08 Python
python 时间戳与格式化时间的转化实现代码
Mar 23 Python
用python实现简单EXCEL数据统计的实例
Jan 24 Python
Python中格式化format()方法详解
Apr 01 Python
Python实现KNN邻近算法
Jan 28 Python
Python线性回归实战分析
Feb 01 Python
python调用百度语音识别api
Aug 30 Python
Python Numpy,mask图像的生成详解
Feb 19 Python
Python实现AI换脸功能
Apr 10 Python
python urllib库的使用详解
Apr 13 Python
python实战之一步一步教你绘制小猪佩奇
Apr 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
优化使用mysql存储session的php代码
2008/01/10 PHP
php使用pdo连接mssql server数据库实例
2014/12/25 PHP
php使用google地图应用实例
2014/12/31 PHP
详谈PHP中public,private,protected,abstract等关键字的用法
2017/12/31 PHP
laravel返回统一格式错误码问题
2019/11/04 PHP
在chrome中window.onload事件的一些问题
2010/03/01 Javascript
深入理解JavaScript定时机制
2010/10/29 Javascript
jquery应该如何来设置改变按钮input的onclick事件
2012/12/10 Javascript
ie支持function.bind()方法实现代码
2012/12/27 Javascript
jquery上传插件fineuploader上传文件使用方法(jquery图片上传插件)
2013/12/05 Javascript
JS实现的N多简单无缝滚动代码(包含图文效果)
2015/11/06 Javascript
快速解决js中window.location.href不工作的问题
2016/11/02 Javascript
用js实现before和after伪类的样式修改的示例代码
2017/09/07 Javascript
基于JavaScript实现幸运抽奖页面
2020/07/05 Javascript
微信小程序在地图选择地址并返回经纬度简单示例
2018/12/03 Javascript
优雅的将ElementUI表格变身成树形表格的方法步骤
2019/04/11 Javascript
vue使用微信JS-SDK实现分享功能
2019/08/23 Javascript
jQuery+ajax实现用户登录验证
2020/09/13 jQuery
Python读写Excel文件的实例
2013/11/01 Python
浅谈机器学习需要的了解的十大算法
2017/12/15 Python
Python中getpass模块无回显输入源码解析
2018/01/11 Python
python实现日常记账本小程序
2018/03/10 Python
详解python实现识别手写MNIST数字集的程序
2018/08/03 Python
Django之form组件自动校验数据实现
2020/01/14 Python
编辑求职信样本
2013/12/16 职场文书
应届毕业生求职信范例分享
2013/12/17 职场文书
实验教师岗位职责
2014/02/13 职场文书
文明市民先进事迹
2014/05/15 职场文书
师范生求职信
2014/06/14 职场文书
小学庆六一活动总结
2014/08/28 职场文书
关于运动会广播稿300字
2014/10/05 职场文书
城管年度个人总结
2015/02/28 职场文书
2015年人力资源工作总结
2015/04/08 职场文书
2015秋季幼儿园开学通知
2015/07/16 职场文书
2015年秋季开学典礼校长致辞
2015/07/16 职场文书
回门宴新娘答谢词
2015/09/29 职场文书