crazy-heng
天降大任于斯人也...

导航

 

实现目标

在数据列表页面,用户选中checkbox后再选中批量操作的动作后点击执行,完成操作

 

实现思路

  1. 前端页面给每行数据添加checkbox选项
  2. 前端页面添加下拉菜单,因为以后拓展需求大了,批量操作动作比较多,排列在页面上不好看,利用select和option选项比较好
  3. 给select设置name属性,给option设置value属性和文本属性
  4. 给checkbox设置value属性和name属性
  5. 后台给出接口,让应用选择批量操作的动作
  6. 后台编写相对应动作的处理函数
  7. 通过POST请求拿到option的value属性和checkbox的value属性
  8. 拓展函数参数

 

具体实现与知识点

给checkbox设置value属性和name属性

我们之前利用display_xx函数实现了在页面上定制添加列,所以我们现在需要给每一行数据添加checkbox选项也使用这个方法,需要注意的地方是,我们在后面进行批量操作的时候,需要拿到每一行数据对应的ID后才能进行操作,进行POST请求的时应该把checkbox选中的数据的ID传递到后台。

在编写checkbox时给他设置一个value值,还需要设置一个name,以方便在POST数据中拿到value值

    def display_checkbox(self, obj=None, is_header=None):
        """
        为每行数据显示checkbox选项
        :param obj:
        :param is_header:
        :return:
        """
        if is_header:
            return '选项'  # 表头
        return mark_safe('<input type="checkbox" value="%s" name="check">' % obj.pk)  #value值设置为每次循环对象的.pk,实际就是每一个数据的ID值

 

在应用层定制的list_display列表中将 display_checkbox函数添加到列表第一个数据即实现前端添加checkbox选项

 

 

前端中,批量操作的下拉菜单根据用户定制而显示

按照我们之前的做法,在应用层面设置一个批量操作列表action_list,将批量操作函数放入列表,把action_list传入前端中,在前端中循环action_list,得到每个函数对象。但是在前端中想要取到我们定制的函数中文名称该怎么办呢?

 

函数的text属性


我们在后端可以给函数设置一个text属性,在前端中直接取该函数的text属性

后端视图函数.py

    def action_multi_delete(self, requset):
        """
        批量处理删除的函数
        :param requset: 
        :return: 
        """
        pass

    action_multi_delete.text = '批量删除'  # 对批量操作的函数设置一个text属性,用于前端显示中文

 

前端.html

<select class="form-control" name="action" id="">
  <option>请选择操作</option>
    {% for func in action_list %}    # 循环后台传入的action_list列表,列表中是每个批量操作的函数
    <option>{{ func.text }}</option>
    {% endfor %}
</select>

 

然而! 我们按照这个思路却无法实现。

 

 

我们看到,在前端中没有读取到函数.text值, 但是我们发现,在action_list中有两个函数,前端中的select下来款中也是两个下拉选项。

    def changelist_view(self, request):
        """
        用户列表函数
        :return:
        """
        # 1 处理批量操作
        action_list = self.get_action_list()
        for item in action_list:
            print('测试:', item.text)

输出:

测试: 批量删除
测试: 批量初始化

我们发现,在前端中虽然没有显示中文内容,但是数量是和我们的action_list列表中函数个数相对于的。

这是为什么呢?

因为在前端{{ }}语法中传入函数,默认是不用加括号就执行函数。所以并不会按照我们想要的去获取函数的text属性

那我们应该如何在前端页面中显示后端传入函数的text属性呢?

我们需要对action_list数据进行调整,调整数据结构。  

这里的思路是利用字典的key,value来处理数据格式, 我们可以设计成 action_dict = {'函数名': '函数.text'}, 这样我们不但得到了 函数.text,我们还拿到了函数名。 这个东西非常有用。

但是,我们如何拿到函数的字符串形式的函数名呢?

利用函数.__name__属性

def my_func_name():
    pass


print(my_func_name.__name__)  # 函数的__name__属性会返回函数的函数名

函数的__name___会得到该函数的字符串形式的函数名

 

这样我们在action_dict中得到的数据格式就是: {'test_func_name': '测试函数文本'}  ,在前端中对action_dict进行循环,文本内容就为函数的text属性。

设置option的value属性

我们根据获取用户选择的option可以拿到用户想要执行的函数,那我们的value值如果直接设置成函数名,在后端中就可以根据函数名找到对应的函数去执行。

所以在action_dict数据设计上选择的模式是非常巧妙的,即解决了显示文本,还一次性把需要执行的函数名称也传到后端中去了。

前端中对整个表格进行form表单的POST数据发送,在后端中通过获取POST请求中select的name值,可以拿到select下面option的value值,自然就拿到批量操作动作对应的函数名

 

根据函数名去执行相对于的函数

利用反射!

拿到字符串的函数名后通过反射可以得到函数对象,并且执行。

    def changelist_view(self, request):
        """
        用户列表函数
        :return:
        """
        # 1 处理批量操作
        action_list = self.get_action_list()

        action_dict = {func.__name__: func.text for func in action_list}
        if request.method == 'POST':
            action_func_name = request.POST.get('action')  # 获取select的name属性可以得到option的value值
            if action_func_name or action_func_name in action_dict:
                getattr(self, action_func_name)(request)  

 

知识点总结: 主要利用了对action_dict格式的设计,实现了文本定制和传递函数名称, 后端中利用反射在拿到名称的情况下获取到函数对象并执行

 

重要知识点: 格式设计、 反射

 

posted on 2019-06-06 09:57  killer-147  阅读(416)  评论(0编辑  收藏  举报