美文网首页Python Web开发学习
【CRM客户关系管理】17.多选字段filter_horizon

【CRM客户关系管理】17.多选字段filter_horizon

作者: 吾星喵 | 来源:发表于2018-12-23 15:24 被阅读1次

多选字段filter_horizontal的实现

Django Admin实现方式

Django admin后台显示效果

在admin.py中注册

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'],效果如下

image.png

如果有,效果如下

image.png

当数据量很大的时候,可以通过搜索批量添加。

djadmin中实现filter_horizontal

在父类和子类中添加filter_horizontal字段

首先在djadmin应用djadmin_base.py中添加filter_horizontal空列表

# djadmin/djadmin_base.py


class BaseDjAdmin(object):
    list_display = []
    list_filter = []
    search_fields = []
    readonly_fields = []
    filter_horizontal = []

修改crm应用的djadmin.py增加filter_horizontal字段

# 注册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,增加获取多对多字段关联表的所有数据

@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),所以前端在引用自定用模板标签的时候可以定义一个变量,里面就保存了所有后台传过来的数据

{% 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/ 发现,选择列表都显示在该框内了

image.png

已选择数据展示右方

现在需要在右边增加一个select框,用于存放已选中的,修改djadmin_tags.py增加一个模板标签,用来获取已选择的数据

@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多选框右边增加已选中数据

<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>
image.png

现在右边已经显示已选中的数据,但是左边不应该显示已被选中的数据,需要进行排序

未选择数据展示左方

修改table_edit.html,将form_obj传给获取可选数据的模板标签中

<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>

通过集合求差集过滤排除左边已选咨询课程数据

@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
多选框多选框

相关文章

网友评论

    本文标题:【CRM客户关系管理】17.多选字段filter_horizon

    本文链接:https://www.haomeiwen.com/subject/xvdnkqtx.html