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的值所有报错),下一章解决

     
     
     
  • 相关阅读:
    Codeforces Beta Round #92 (Div. 2 Only) B. Permutations 模拟
    POJ 3281 Dining 最大流 Dinic算法
    POJ 2441 Arrange the BUlls 状压DP
    URAL 1152 Faise Mirrors 状压DP 简单题
    URAL 1039 Anniversary Party 树形DP 水题
    URAL 1018 Binary Apple Tree 树形DP 好题 经典
    pytorch中的forward前向传播机制
    .data()与.detach()的区别
    Argparse模块
    pytorch代码调试工具
  • 原文地址:https://www.cnblogs.com/gaidy/p/12101973.html
Copyright © 2011-2022 走看看