您现在的位置是: 网站首页 >Django >DjangoCRM客户关系管理 Django

【CRM客户关系管理】17.多选字段filter_horizontal的实现,已选和未选数据展示

admin2018年12月23日 15:20 Django | JavaScript | JQuery | Python 193人已围观

DjangoCRM客户关系管理简介 使用Django2.1.3+Bootstrap实现CRM系统,仿照Django Admin重写后台 Github地址:https://github.com/xyliurui/DjangoCRM Django版本:2.1.3

## 多选字段filter_horizontal的实现 ### Django Admin实现方式 Django admin后台显示效果 在admin.py中注册 ```python class CustomerInfoAdmin(admin.ModelAdmin): list_display = ['name', 'contact_type', 'contact', 'consultant', 'consult_content', 'status', 'created_time'] list_filter = ['source', 'consultant', 'status', 'created_time'] search_fields = ['contact', 'consultant__name', 'consult_content'] readonly_fields = ['contact', 'status'] filter_horizontal = ['consult_courses'] admin.site.register(CustomerInfo, CustomerInfoAdmin) ``` 如果没有`filter_horizontal = ['consult_courses']`,效果如下 ![BLOG_20181223_152140_22](/media/blog/images/2018/12/BLOG_20181223_152140_22.png "博客图集BLOG_20181223_152140_22.png") 如果有,效果如下 ![BLOG_20181223_152159_13](/media/blog/images/2018/12/BLOG_20181223_152159_13.png "博客图集BLOG_20181223_152159_13.png") 当数据量很大的时候,可以通过搜索批量添加。 ### djadmin中实现filter_horizontal #### 在父类和子类中添加filter_horizontal字段 首先在djadmin应用djadmin_base.py中添加`filter_horizontal`空列表 ```python # djadmin/djadmin_base.py class BaseDjAdmin(object): list_display = [] list_filter = [] search_fields = [] readonly_fields = [] filter_horizontal = [] ``` 修改crm应用的djadmin.py增加`filter_horizontal`字段 ```python # 注册model class CustomerInfoAdmin(BaseDjAdmin): # 不使用object,直接继承BaseDjAdmin list_display = ['name', 'contact_type', 'contact', 'consultant', 'consult_content', 'status', 'created_time'] list_filter = ['source', 'consultant', 'status', 'created_time'] search_fields = ['contact', 'consultant__name', 'consult_content'] readonly_fields = ['contact', 'status'] filter_horizontal = ['consult_courses'] site.register(models.CustomerInfo, CustomerInfoAdmin) ``` #### 获取多对多关联表数据 修改djadmin应用的模板标签djadmin_tags.py,增加获取多对多字段关联表的所有数据 ```python @register.simple_tag def get_available_m2m_data(field_name, admin_class): """获取多对多字段关联表的所有数据""" field_obj = admin_class.model._meta.get_field(field_name) # 获取字段对象 # consult_courses = models.ManyToManyField(Course, verbose_name='咨询课程') # 多对多关联课程 # 这是一个多对多字段,通过consult_courses对象获取到Course,也就是获取到所有咨询的课程 obj_list = field_obj.related_model.objects.all() return obj_list ``` #### 模板中展示多选框 修改djadmin应用templates/djadmin/table_edit.html,当遍历的字段在多选列表内,就使用多选的样式 `{% get_available_m2m_data field.name admin_class as available_m2m_data %}` 后面的的 `as availavle_m2m_data` 是定义一个变量(里面存了自定义模板标签里面返回的数据 `return obj_list`) 因为在前端不能直接循环从后台返回的queryset数据(obj_list),所以前端在引用自定用模板标签的时候可以定义一个变量,里面就保存了所有后台传过来的数据 ```html {% extends 'djadmin/base.html' %} {% load djadmin_tags %} {% block title %} 数据表编辑 - 后台管理 {% endblock %} {% block content %} <h1 class="page-header">{{ app_name }} - {{ model_name }} - 编辑 &nbsp;&nbsp; {{ obj }} </h1> <!--<div>{{ form_obj }}</div>--> <form class="form-horizontal" method="post"> {{ form_obj.errors }} {% for field in form_obj %} <div class="form-group"> <label class="col-sm-2 control-label">{{ field.label }}</label> <div class="col-sm-10"> {% if field.name in admin_class.filter_horizontal %} <!--字段名在多选的字段中,使用多选框--> <div class="col-md-5"> <select multiple class="form-control"> {% get_available_m2m_data field.name admin_class as vailable_m2m_data %} {% for obj in vailable_m2m_data %} <option value="{{ obj.id }}">{{ obj }}</option> {% endfor %} </select> </div> {% else %} {{ field }} {% endif %} <span style="color: red">{{ field.errors.0 }}</span> </div> </div> {% endfor %} {% csrf_token %} {% if not admin_class.form_add %} {# 当修改数据时,才显示下方只读字段,当增加数据时,下方则不会显示 #} {% for field in admin_class.readonly_fields %} <label class="col-sm-2 control-label">{{ field }}</label> <div class="col-sm-10"> <p>{% get_obj_field_val form_obj field %}</p> </div> {% endfor %} {% endif %} <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-primary">提交</button> </div> </div> </form> {% endblock %} ``` 访问 http://127.0.0.1:8000/djadmin/crm/customerinfo/1/change/ 发现,选择列表都显示在该框内了 ![BLOG_20181223_152309_65](/media/blog/images/2018/12/BLOG_20181223_152309_65.png "博客图集BLOG_20181223_152309_65.png") #### 已选择数据展示右方 现在需要在右边增加一个select框,用于存放已选中的,修改djadmin_tags.py增加一个模板标签,用来获取已选择的数据 ```python @register.simple_tag def get_selected_m2m_data(field_name, form_obj, admin_class): """获取已选中的多对多数据""" selected_data = getattr(form_obj.instance, field_name).all() return selected_data ``` 在table_edit.html多选框右边增加已选中数据 ```html <div class="col-sm-10"> {% if field.name in admin_class.filter_horizontal %} <!--字段名在多选的字段中,使用多选框--> <div class="col-md-5"> <select multiple class="form-control"> {% get_available_m2m_data field.name admin_class as vailable_m2m_data %} {% for obj in vailable_m2m_data %} <option value="{{ obj.id }}">{{ obj }}</option> {% endfor %} </select> </div> <div class="col-md-5"> <select multiple class="form-control"> {% get_selected_m2m_data field.name form_obj admin_class as selected_m2m_data %} {% for obj in selected_m2m_data %} <option value="{{ obj.id }}">{{ obj }}</option> {% endfor %} </select> </div> {% else %} {{ field }} {% endif %} <span style="color: red">{{ field.errors.0 }}</span> </div> ``` ![BLOG_20181223_152407_68](/media/blog/images/2018/12/BLOG_20181223_152407_68.png "博客图集BLOG_20181223_152407_68.png") 现在右边已经显示已选中的数据,但是左边不应该显示已被选中的数据,需要进行排序 #### 未选择数据展示左方 修改table_edit.html,将`form_obj`传给获取可选数据的模板标签中 ```html <div class="col-md-5"> <select multiple class="form-control"> {% get_available_m2m_data field.name form_obj admin_class as vailable_m2m_data %} {% for obj in vailable_m2m_data %} <option value="{{ obj.id }}">{{ obj }}</option> {% endfor %} </select> </div> ``` 通过集合求差集过滤排除左边已选咨询课程数据 ```python @register.simple_tag def get_available_m2m_data(field_name, form_obj, admin_class): """获取多对多字段关联表的所有数据""" field_obj = admin_class.model._meta.get_field(field_name) # 获取字段对象 # consult_courses = models.ManyToManyField(Course, verbose_name='咨询课程') # 多对多关联课程 # 这是一个多对多字段,通过consult_courses对象获取到Course,也就是获取到所有咨询的课程 obj_list = field_obj.related_model.objects.all() obj_list = set(obj_list) # 所有咨询课程的集合 selected_data = set(getattr(form_obj.instance, field_name).all()) # 所以已选中课程的即可 # 通过集合求差集,得到未选中的自选课程,填充到左边多选框中 return obj_list - selected_data ``` ![BLOG_20181223_152441_59](/media/blog/images/2018/12/BLOG_20181223_152441_59.png "博客图集BLOG_20181223_152441_59.png")

很赞哦! (0)

文章交流

  • emoji
0人参与,0条评论

当前用户

未登录,点击   登录

站点信息

  • 建站时间:网站已运行552天
  • 系统信息:Linux
  • 后台程序:Python: 3.6.6
  • 网站框架:Django: 2.2.9
  • 文章统计:219 篇
  • 文章评论:37 条
  • 腾讯分析网站概况-腾讯分析
  • 百度统计网站概况-百度统计
  • 微信公众号:扫描二维码,关注我们
返回
顶部
标题 换行 登录
网站