ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

stark组件之显示页面内容搭建(六)

2019-05-23 13:42:04  阅读:285  来源: 互联网

标签:obj val list stark field 组件 页面 data row


之前主要介绍了前端页面list_fiter功能的显示,但是list_display功能的展示并没有过多介绍,这里介绍一下是如何实现的。

可以看到凡是蓝线圈起来的都是通过字段名反射一个个取出来的,红线的是通过函数来构造的,这也就说明,list_display中单是字段名是不够的,还需要加入一些数据库中没有的东西。这里可以加入字段以及构建的函数。

    list_display = [BaseStark.display_checkbox,'id','name','contact','status','source','referral_from','product','consultant','consultant_date',display_follow,display_order]

那么怎么对它进行处理呢?

表头处理:

    def header_list(self,request,*args,**kwargs):
        list_display = self.get_list_display()
        if list_display:
            for field in list_display:
                if isinstance(field, FunctionType):
                    header_name = field(self, row=None, header_body=False, *args, **kwargs)  # 加后面的编辑框
                else:
                    header_name = self.model_class._meta.get_field(field).verbose_name  # 获取对应字段的verbose_name
                yield header_name
        else:
            yield self.model_class._meta.model_name  # 如果list_display中没有值显示表名

表内容处理:

    def body_list(self,request,queryset,*args,**kwargs):
        list_display = self.get_list_display()
        for row in queryset:
            row_list = []  # 注意必须放在这个循环下面
            if not list_display:  # list_display中没有值
                row_list.append(row)
                yield row_list
                continue
            for field_or_func in list_display:

                # list_display中有值
                if isinstance(field_or_func, FunctionType):
                    val = field_or_func(self, row=row, header_body=True, *args, **kwargs)
                elif field_or_func in self.list_editable:
                    val = self.render_editable_value(row,field_or_func)
                else:
                    field_obj = self.model_class._meta.get_field(field_or_func)  # 获取字段对象
                    if field_obj.choices:
                        val = getattr(row, "get_%s_display" % field_or_func)()
                    elif isinstance(field_obj, ManyToManyField):
                        queryset = getattr(row, field_or_func).all()  # ManyToManyField反射需要加all()
                        val_list = []
                        for obj in queryset:
                            val_list.append(str(obj))
                        val = '、'.join(val_list)
                    else:
                        val = getattr(row, field_or_func)  # ForeignKey字段反射,ManyToManyField会出现问题
                    if not val:
                        val = ''
                row_list.append(val)
            yield row_list

在这里对list_display中的字段进行了判断,普通字段、Foreignkey、ManyToMany、函数分别做不同的处理。另外在循环list_display的过程中引入list_editable的功能,那么它又是怎么完成的呢?

其实就是将ForeignKey以及choice类型的字段变成select标签,每一个option的value值就是它们自身的id,普通字段就给它变成input框就可以了。

  def render_editable_value(self,row,field_or_func):
        field_obj = self.model_class._meta.get_field(field_or_func)  # 获取字段对象
        if hasattr(row,field_or_func):
            if field_obj.get_internal_type() == "ForeignKey":
                field_val=getattr(row,"%s_id"%(field_obj.name))
            else:
                field_val=getattr(row,field_or_func)
        else:
            field_val=''
        if not field_obj.choices and field_obj.get_internal_type() != "ForeignKey" :
            if field_obj.get_internal_type() == "DateTimeField":
                val = '''<input data-tag='editable' class='form-control' type='text' name='%s' value='%s'  date_time='datetimepicker'>''' % (field_obj.name, getattr(row, field_obj.name) or '')
            else:
                val = '''<input data-tag='editable' class='form-control' type='text' name='%s' value='%s' >''' %(field_obj.name,getattr(row,field_obj.name) or '')
        else:
            val = '''<select data-tag='editable' class='form-control'  name='%s' >''' % field_obj.name
            for option in field_obj.get_choices():
                if option[0] == field_val:
                    selected_attr = "selected"
                else:
                    selected_attr = ''
                val += '''<option value='%s' %s >%s</option>'''% (option[0],selected_attr,option[1])
        return mark_safe(val)

这里有一个注意的地方,字段对象如果是choice或者foreignker类型都可以使用field_obj.get_choice(),取到的就是一个个元组组成的列表,前台通过list_editable修改完成后通过ajax进行数据发送。只发送那些改动过的数据。

    <table class="table table-hover table-bordered table_content">
        <thead >
            <tr>
                   {% for row in cl.header_list %}
                       <th class="table_content">{{ row }}</th>
                        {% endfor %}
            </tr>
        </thead>
    <tbody id="model_table_data">
           {% for row_list in cl.body_list %}
            <tr>
           {% for val in row_list  %}
               <td>{{ val }}</td>
               {% endfor %}
            </tr>
        {% endfor %}
    </tbody>

    </table>
function SendData() {
        $('#submit').click(function () {

            var $action_val=$('#action').val();
            var form_data = [{"action":$action_val}];
            $("#model_table_data tr").each(function () {
                        var obj_id = $(this).children().first().find("input").val();
                        if (obj_id){ 
                            var row_data = {};
                            $(this).find("[data-tag='editable']").each(function () {
                                var val=$(this).val();
                                row_data[$(this).attr("name")] = $(this).val();
                            });//end find each
                            row_data['id'] = obj_id;
            
                            form_data.push(row_data);

                        }
            
                    });//end each
            
            {#alert(JSON.stringify(form_data));#}
            $.ajax({
                headers:{'X-CSRFToken':$.cookie('csrftoken')},
                type:'POST',
                dataType:"JSON",
                contentType:"application/json",
                 data:JSON.stringify(form_data),
                success:function (arg) {
                }
                
            })


        })

    }

这样就将需要更改的数据发送到后台了,但是是否注意,我发送ajax数据时,另外还发送了一个action的数据,这又是干什么呢?实际上在页面上我有action_list这么一个功能,在这里,将action_list选项的功能变成既可以发送form表单数据,也可以进行ajax发送,然后在后台根据发送过来的函数名称进行反射处理即可。

   {% if cl.action_list %}
    <div class="form-group" style="padding: 5px 0">
    <select id="action" name="action" class="form-control" style="min-width: 200px;">
        <option value="">请选择相应的功能</option>
        {% for item in cl.action_list %}
                <option value="{{ item.name }}">{{ item.attr_dict.text }}</option>
    </select>
        {% if item.attr_dict.id %}
        <input type="button" value="执行" id="{{ item.attr_dict.id }}" class="btn btn-primary">
            {% else %}
          <input type="submit" value="执行" class="btn btn-primary">
        {% endif %}
    {% endfor %}
    </div>
    {% endif %}

后台处理list_editable功能的函数

    def changelist_view(self, request,*args,**kwargs):
        """
        处理显示数据的页面
        :param request:
        :return:
        """

        if request.method == 'POST':
            editable_data=str(request.body,encoding='utf-8')
            if editable_data:
                editable_data=json.loads(editable_data)
            action_name=editable_data[0].get('action') #ajax请求

            action_name = request.POST.get('action') or action_name  # 普通form表单请求
            if action_name:
                if action_name not in self.get_action_dict():  # 防止前端客户刻意修改代码,进行验证
                    return HttpResponse('非法请求!')
                response = getattr(self, action_name)(request,*args,**kwargs)  # 反射执行函数 action_name就是函数名称
                if response:
                    return response  # 返回什么结果就是什么

执行反射的函数

def muti_editable_save(self, request,*args,**kwargs):
    """
    ajax实现list_editble保存,通过判断是否有id属性 muti_editable_save.attr_dict = {'text':'批量保存','id':'submit'}
    :param request:
    :param args:
    :param kwargs:
    :return:
    """
    editable_data = str(request.body, encoding='utf-8')
    if editable_data:
        editable_data = json.loads(editable_data) ## for list editable
        del editable_data[0]
    #print('反射',editable_data) # [{'confirm_user': '7', 'confirm_date': '1899-12-13 09:50:00+00:00', 'id': '2'}]
    for row_data in editable_data:
        obj_id = row_data.get('id')
        if obj_id:
            #print("editable data", row_data, list(row_data.keys()))#['id', 'confirm_user', 'confirm_date']
            obj = self.model_class.objects.get(id=obj_id)
            model_form = self.create_list_editable_model_form(list(row_data.keys()))
            form_obj = model_form(instance=obj, data=row_data)
            if form_obj.is_valid():
                form_obj.save()
muti_editable_save.attr_dict = {'text':'批量保存','id':'submit'}

这样很容易就实现了list_editable的保存,而且以后如果想通过action_list各个功能的话,指的,可以选择ajax发送数据,或者表单发送,只需要在后台中给对应的处理函数赋值相应的id属性就可以了,值得注意的是,如果使用ajax功能的,就必须加上display_checkbox(),因为取id的时候就是通过checkbox中来获取的,这就是列表页面的主要功能了。

 

标签:obj,val,list,stark,field,组件,页面,data,row
来源: https://www.cnblogs.com/shenjianping/p/10911202.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有