• CRM-批量操作


    实现目标

    在数据列表页面,用户选中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格式的设计,实现了文本定制和传递函数名称, 后端中利用反射在拿到名称的情况下获取到函数对象并执行

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

  • 相关阅读:
    bzoj1648:奶牛野餐
    bzoj1650:跳石子
    bzoj1643:贝西的秘密草坪
    bzoj1639:月度开支
    bzoj1636:Balanced Lineup
    bzoj1634:护花
    .
    bzoj1620:时间管理
    bzoj1611:流星雨
    bzoj1609:麻烦的聚餐
  • 原文地址:https://www.cnblogs.com/aaaajayheng1990/p/10983337.html
Copyright © 2020-2023  润新知