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 时间操作例子和时间格式化参数小结
Apr 24 Python
python求crc32值的方法
Oct 05 Python
Python实现的计数排序算法示例
Nov 29 Python
python实现BackPropagation算法
Dec 14 Python
python实现扫描日志关键字的示例
Apr 28 Python
python leetcode 字符串相乘实例详解
Sep 03 Python
python数据批量写入ScrolledText的优化方法
Oct 11 Python
pandas 条件搜索返回列表的方法
Oct 30 Python
Python实战购物车项目的实现参考
Feb 20 Python
Python + OpenCV 实现LBP特征提取的示例代码
Jul 11 Python
使用已经得到的keras模型识别自己手写的数字方式
Jun 29 Python
python中validators库的使用方法详解
Sep 23 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小偷程序)
2014/08/23 PHP
php邮箱地址正则表达式验证
2015/11/13 PHP
获取JavaScript用户自定义类的类名称的代码
2007/03/08 Javascript
基于jquery点击自以外任意处,关闭自身的代码
2012/02/10 Javascript
GridView中获取被点击行中的DropDownList和TextBox中的值
2013/07/18 Javascript
jquery触发a标签跳转事件示例代码
2013/07/21 Javascript
JS自动倒计时30秒后按钮才可用(两种场景)
2015/08/31 Javascript
js实现简洁大方的二级下拉菜单效果代码
2015/09/01 Javascript
使用Bootstrap typeahead插件实现搜索框自动补全的方法
2016/07/07 Javascript
常用的js验证和数据处理总结
2016/08/02 Javascript
微信小程序如何获知用户运行小程序的场景教程
2017/05/17 Javascript
react-native ListView下拉刷新上拉加载实现代码
2017/08/03 Javascript
angular6.x中ngTemplateOutlet指令的使用示例
2018/08/09 Javascript
nodejs提示:cross-device link not permitted, rename错误的解决方法
2019/06/10 NodeJs
微信小程序移动拖拽视图-movable-view实例详解
2019/08/17 Javascript
浅谈Vue3 Composition API如何替换Vue Mixins
2020/04/29 Javascript
[01:20]DOTA2 2017国际邀请赛冠军之路无止竞
2017/06/19 DOTA
[57:47]Fnatic vs Winstrike 2018国际邀请赛小组赛BO2 第二场 8.18
2018/08/19 DOTA
python备份文件以及mysql数据库的脚本代码
2013/06/10 Python
Python内置函数Type()函数一个有趣的用法
2015/02/18 Python
Pycharm学习教程(1) 定制外观
2017/05/02 Python
python opencv 直方图反向投影的方法
2018/02/24 Python
Python网页解析器使用实例详解
2020/05/30 Python
AmazeUI的下载配置与Helloworld的实现
2020/08/19 HTML / CSS
美国综合购物商城:UnbeatableSale.com
2018/11/28 全球购物
夏威夷咖啡公司:Hawaii Coffee Company
2019/09/19 全球购物
经济管理毕业生求职信
2014/03/15 职场文书
保密承诺书范文
2014/03/27 职场文书
冬季施工防火方案
2014/05/17 职场文书
数学兴趣小组活动总结
2014/07/08 职场文书
办公室个人总结
2015/02/28 职场文书
小学教师自我评价
2015/03/04 职场文书
母亲去世追悼词
2015/06/23 职场文书
读书笔记怎么写
2015/07/01 职场文书
Win11黑色桌面背景怎么办?Win11黑色壁纸解决方法汇总
2022/04/05 数码科技
CSS 鼠标点击拖拽效果的实现代码
2022/12/24 HTML / CSS