zoukankan      html  css  js  c++  java
  • CRM客户关系管理系统(八)

    第八章、只读字段处理和filter_horizontal的实现

     8.1.只读字段的处理

    (1)kingadmin/admin_base.py

    # kingadmin/admin_base.py
    
    class BaseKingAdmin(object):
    
        list_display = []
        list_filter = []
        search_fields = []
        #只读
        readonly_fields = []

    (2)crm/kingadmin.py

     (3)kingadmin/form_handle.py

     (4)table_obj_change_component.html

     

    {#kingadmin/templates/kingadmin/table_obj_change_component.html#}
    
    {% load kingadmin_tags %}
    <form class="form-horizontal" method="post">
        {% csrf_token %}
        {{ 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">
                {{ field }}
                <span style="color: red;">{{ field.errors.0 }}</span>
            </div>
        </div>
        {% endfor %}
        
        {% for field in admin_class.readonly_fields %}
        <div class="form-group">
            <label class="col-sm-2 control-label">{{ field }}</label>
            <div class="col-sm-10">
                <p>{% get_obj_field_val form_obj field %}</p>
            </div>
        </div>
        {% endfor %}
    
    
        <div class="form-group">
            <div class="col-sm-offset-11 col-sm-10">
              <button type="submit" class="btn btn-info">Save</button>
            </div>
        </div>
    </form>

     (5)kingadmin_tags.py

    @register.simple_tag
    def get_obj_field_val(form_obj,field):
        '''获取只读字段的值'''
    
        return getattr(form_obj.instance,field)

    现在修改的时候没问题,但是在添加的时候会报错(提示那两个只读字段为空,因为设置成了readonly_field,添加的时候确实没有添加值)

    下面解决这个报错,在前后端都添加一个判断

    (4)kingadmin/views.py

    (5)form_handle.py

     

     (6)table_obj_change_component.html

     

    现在增加和修改就都没问题了

    8.2.filter_horizontal的实现

    默认咨询课程后台显示的样子

     添加filter_horizontal(数据量大的时候很方便)后显示的样子(可以批量添加,还可以在里面搜索)

     

     下面我们在kingadmin中实现这个功能

     (1)kingadmin/admin_base.py

    # kingadmin/admin_base.py
    
    class BaseKingAdmin(object):
    
        list_display = []
        list_filter = []
        search_fields = []
        #只读
        readonly_fields = []
        filter_horizontal = []

    (2)crm/kingadmin.py

     (3)kingadmin/kingadmin_tags.py

    @register.simple_tag
    def get_available_m2m_data(field_name,admin_class):
        '''返回的是m2m字段关联表的所有数据'''
        #获取字段的对象
        field_obj = admin_class.model._meta.get_field(field_name)
    
        #consult_courses = models.ManyToManyField('Course',verbose_name='咨询课程')
        #consult_courses是一个m2m,通过consult_courses对象获取到Course(也就是获取到所有咨询的课程)
        obj_list = field_obj.related_model.objects.all()
    
        return obj_list

    (4)table_obj_change_component.html

    •  在生成field的时候判断在不在filter_horizontal里面,在的话就用我们设置的select下拉框,不在就默认的
    •  {% get_available_m2m_data field.name admin_class as available_m2m_data %}  后面的的 as availavle_m2m_data 是定义一个变量(里面存了自定义模板标签里面返回的数据 return obj_list

        因为在前端不能直接循环从后台返回的querysets数据(obj_list),所以前端在引用自定用模板标签的时候可以定义一个变量,里面就保存了所有后台传过来的数据

    {#kingadmin/templates/kingadmin/table_obj_change_component.html#}
    
    {% load kingadmin_tags %}
    <form class="form-horizontal" method="post">
        {% csrf_token %}
        {{ 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-lg-5">
                        <select multiple class="form-control">
                            {% get_available_m2m_data field.name admin_class as available_m2m_data %}
                            {% for obj in available_m2m_data %}
                                <option value="{{ obj.id }}">{{ obj }}</option>
                            {% endfor %}
                        </select>
                    </div>
                    <div class="col-lg-5"></div>
                {% else %}
                    {{ field }}
                {% endif %}
                <span style="color: red;">{{ field.errors.0 }}</span>
            </div>
        </div>
        {% endfor %}

     效果:

     右边添加一个select框(存放已选中的)

     kingadmin_tags.py

    @register.simple_tag
    def get_selected_m2m_data(field_name,form_obj,admin_class):
        '''返回已选的m2m数据'''
        #获取被选中的数据
        selected_data = getattr(form_obj.instance,field_name).all()
    
        return selected_data

    table_obj_change_component.html

    <div class="col-lg-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>

    效果:

    • 左边不应该显示已被选中的咨询课程了
    • 右边是已选中的咨询课程

    通过集合求差集过滤出左边已选咨询课程

     kingadmin_tags.py

    @register.simple_tag
    def get_available_m2m_data(field_name,form_obj,admin_class):
        '''返回的是m2m字段关联表的所有数据'''
        #获取字段的对象
        field_obj = admin_class.model._meta.get_field(field_name)
        #consult_courses = models.ManyToManyField('Course',verbose_name='咨询课程')
        #consult_courses是一个m2m,通过consult_courses对象获取到Course(也就是获取到所有咨询的课程)
        #所有咨询课程的集合
        obj_list = set(field_obj.related_model.objects.all())
        #选中的咨询课程集合
        selected_data = set(getattr(form_obj.instance, field_name).all())
        #返回的时候,集合求差集,得到未选中的咨询课程(左边)
        return obj_list - selected_data

    效果:

    js触发事件

    table_obj_change_component.html

    可以通过双击咨询课程,来选择

    {#kingadmin/templates/kingadmin/table_obj_change_component.html#}
    
    {% load kingadmin_tags %}
    
    <form class="form-horizontal"  method="post" onsubmit="VerificationBeforeFormSubmit()"> {% csrf_token %}
     {{ 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-lg-5">
                    <select id="id_{{ field.name }}_from" multiple class="form-control">
                        {% get_available_m2m_data field.name form_obj admin_class as available_m2m_data %}
                        {% for obj in available_m2m_data %}
                            <option ondblclick="MoveSelectedOption(this,'id_{{ field.name }}_to')" value="{{ obj.id }}">{{ obj }}</option>
                        {% endfor %}
                    </select>
              </div>
              <div class="col-lg-5">
                    <select tag="selected_m2m" id="id_{{ field.name }}_to" multiple class="form-control" name="{{ field.name }}">
                        {%  get_selected_m2m_data field.name form_obj admin_class as selected_m2m_data %}
                        {% for obj in selected_m2m_data %}
                            <option value="{{ obj.id }}" ondblclick="MoveSelectedOption(this,'id_{{ field.name }}_from')">{{ obj }}</option>
                        {% endfor %}
    
                    </select>
    
              </div>
          {% else %}
            {{ field }}
          {% endif %}
            <span style="color: red">{{ field.errors.0 }} </span>
        </div>
      </div>
      {% endfor %}
      {% if not admin_class.form_add %}   <!--如果这是修改表单-->
          {% for field in admin_class.readonly_fields %}
          <div class="form-group">
            <label class="col-sm-2 control-label">{{ field }}</label>
            <div class="col-sm-10">
              <p>{% get_obj_field_val form_obj field %}</p>
            </div>
          </div>
          {% endfor %}
     {% endif %}
      <div class="form-group">
        <div class="col-sm-offset-11 col-sm-2">
          <button type="submit" class="btn btn-info">Save</button>
        </div>
      </div>
    </form>
    
    
    <script>
    
        function  MoveSelectedOption(ele,target_id) {
    
            var new_target_id = $(ele).parent().attr('id');
            var option = "<option value='" + $(ele).val() +"'ondblclick=MoveSelectedOption(this,'"+ new_target_id +"') >" + $(ele).text() +"</option>";
            $("#"+ target_id).append(option);
            $(ele).remove();
    
        }
    
    
        function VerificationBeforeFormSubmit() {
    
    
            $("select[tag] option").prop('selected',true);
    
        }
    </script>

    现在保存的时候没有问题,但是 添加的时候会报错(因为添加的时候,值都是为空,获取不到filter_horizontal的值所有报错),下一章解决

     
     
     
  • 相关阅读:
    Spring Security配置logout地址
    flex布局
    视口的学习笔记
    box-sizing属性
    css清除浮动
    line-height的理解
    position和float小结
    css居中方法小结
    margin重叠
    浅谈负margin
  • 原文地址:https://www.cnblogs.com/gaidy/p/12101973.html
Copyright © 2011-2022 走看看