【CRM客户关系管理】18.多选字段filter_horizontal的实现,js移动多选框数据和过滤

js实现多选框数据移动

js实现左右多选框移动数据

为左边的select增加一个id="id_{{ field.name }}_from",为右边的select增加一个id="id_{{ field.name }}_to"

为左边的option增加一个双击事件ondblclick="MoveSelectedOption(this,'id_{{ field.name }}_to')",为右边的option增加一个双击事件ondblclick="MoveSelectedOption(this,'id_{{ field.name }}_from')"

查看编辑表单的客户姓名这一栏


以上{{ field }}自动生成了id和name等

所以需要在右边的多选框增加name字段:name="{{ field.name }}">

{% if field.name in admin_class.filter_horizontal %}
{% else %} {{ field }} {% endif %} {{ field.errors.0 }}

然后再{% endblock %}块前增加js用于多选框移除移入


当双击咨询课程左边多选框内的数据,就会移动到右边多选框,当双击右边多选框内的数据,就会移动到左边多选框。

访问 http://127.0.0.1:8000/djadmin/crm/customerinfo/1/change/ ,修改咨询课程,然后提交保存,但会出现以下提示

image.png

说明name="{{ field.name }}">所在的select中的option没有一个为选中状态

js实现提交表单selected已选择数据

修改form表单提交的验证函数调用

。。。

定义一个提交选中右方所有选项的js函数


由于这个全选没有一个id或者是class找到右方的多选框,所以自定义一个myflag="selected_m2m"

现在提交时就会把右方的多选框全选,进行提交。

如果不自定义,如下


当表单提交时,所有的选框select--option都会被选中!这就回造成如果有单选框是不能保存。

最终table_edit.html内容是

{% extends 'djadmin/base.html' %}

{% load djadmin_tags %}

{% block title %}
    数据表编辑 - 后台管理
{% endblock %}

{% block content %}
    

{{ app_name }} - {{ model_name }} - 编辑    {{ obj }}

{{ form_obj.errors }} {% for field in form_obj %}
{% if field.name in admin_class.filter_horizontal %}
{% else %} {{ field }} {% endif %} {{ field.errors.0 }}
{% endfor %} {% csrf_token %} {% if not admin_class.form_add %} {# 当修改数据时,才显示下方只读字段,当增加数据时,下方则不会显示 #} {% for field in admin_class.readonly_fields %}

{% get_obj_field_val form_obj field %}

{% endfor %} {% endif %}
{% endblock %}
image.png

解决添加数据报错问题

现在更新数据就可以用了。但添加数据会报错。

错误提示是ValueError: "" needs to have a value for field "id" before this many-to-many relationship can be used.查看报错位置是模板标签中的selected_data = getattr(form_obj.instance, field_name).all(),当修改数据,获取所有的已选择数据,当添加数据时,已选择为空,这儿就会报错,暂时使用try来捕获该异常,修改下面的模板标签

@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)  # 所有咨询课程的集合
    try:
        selected_data = set(getattr(form_obj.instance, field_name).all())  # 所以已选中课程的即可
    except:
        selected_data = set([])
    # 通过集合求差集,得到未选中的自选课程,填充到左边多选框中
    return obj_list - selected_data


@register.simple_tag
def get_selected_m2m_data(field_name, form_obj, admin_class):
    """获取已选中的多对多数据"""
    try:
        selected_data = getattr(form_obj.instance, field_name).all()
    except:
        selected_data = set([])
    # print(selected_data)

    return selected_data

现在访问 http://127.0.0.1:8000/djadmin/crm/customerinfo/add/ 不会报错,并且可以正常添加数据

image.png

添加全选和删除全部功能

image.png

修改table_edit.html增加a标签和js函数,用于选择全部,以及移除选择功能

{% if field.name in admin_class.filter_horizontal %}
    
    

全选>

<删除全部

{% else %} {{ field }} {% endif %}

添加js函数实现该功能


访问 http://127.0.0.1:8000/djadmin/crm/customerinfo/1/change/

点击删除全部,就会把所有已到左方

image.png

点击全选就会把所有移动到右方

image.png

添加数据页面功能也正常

多框框过滤功能

类似于Django Admin的选择框所有

创建搜索框

在左方多选框上增加一个type="search"的input标签

全选>

js实现搜索过滤


现在在输入框中输入值就会过滤下方的多选框内容。

image.png
image.png

最终table_edit.html代码如下

{% extends 'djadmin/base.html' %}

{% load djadmin_tags %}

{% block title %}
    数据表编辑 - 后台管理
{% endblock %}

{% block content %}
    

{{ app_name }} - {{ model_name }} - 编辑    {{ obj }}

{{ form_obj.errors }} {% for field in form_obj %}
{% if field.name in admin_class.filter_horizontal %}

全选>

<删除全部

{% else %} {{ field }} {% endif %} {{ field.errors.0 }}
{% endfor %} {% csrf_token %} {% if not admin_class.form_add %} {# 当修改数据时,才显示下方只读字段,当增加数据时,下方则不会显示 #} {% for field in admin_class.readonly_fields %}

{% get_obj_field_val form_obj field %}

{% endfor %} {% endif %}
{% endblock %}

你可能感兴趣的:(【CRM客户关系管理】18.多选字段filter_horizontal的实现,js移动多选框数据和过滤)