zoukankan      html  css  js  c++  java
  • Xadmin控件的实现:〇七查询视图五——list视图action功能

    action功能主要用于批量的操作,主要是结合select标签一起使用,admin控件在不设置的时候默认包含了一个删除所有已选择的对象。

     我们还可以自定义action,就是在自定义的配置类里写一个函数,然后把这个函数名添加到列表里。

    整体思路

     我们主要来看一下当我们点击了go按钮以后发生了什么事情:

    两组键值对

    检查一下点击go按钮以后,其实是发送了一个POST请求的过程,提交请求的时候带了两组键值对,一个是action自己下拉菜单里的值,还有一组就是checkbox对应的值。而先选函数或者先选checkbox是没有影响的,只是最后点击go按钮的时候进行submit提交表单的时候才获取最终的值。

    下拉列表的构造

    下拉列表里的内容要怎么获取呢?在配置累里有个列表,actions = [],默认情况是没有值得

    在自定义配置类的时候,可以自定义一个函数,然后怎么把这个函数的名称显示在下拉列表里呢?

     1 class BookConf(ConfXadmin):
     2     list_display = deepcopy(ConfXadmin.list_display)
     3     list_display.append('price',)
     4     search_fields = ['title','price']
     5 
     6     def patch_init(self,queryset):
     7         print(queryset)
     8 
     9     patch_init.desc = '测试用action'
    10     actions = [patch_init]

    注意最后一行的代码,我们是把函数对象放在列表里的,然后在定义一个函数

    1 def get_actions_name(self):
    2     temp = []
    3     for action in self.actions:
    4         temp.append(action.__name__)
    5 
    6     return temp

    直接把函数名放在一个列表里返回就可以了,然后我们在模板中调用这个函数

    <select name="action" id="" style=" 200px; padding: 5px,8px;display: inline-block;">
        <option value="">--------------</option>
        {%for action in view_obj.conf_obj.get_actions_name%}
        <option value="">{{action}}</option>
        {%endfor%}
    </select>

    这样用一个for循环就能生成需要的列表里

    按自定义要求显示函数名

    admin中是可以通过一个参数short_description来指定显示在下拉列表里的函数的函数名,那么我们怎么实现这个功能呢?

    1 def get_actions_desc(self):
    2     temp = []
    3     for action in self.actions:
    4         temp.append({'name':action.__name__,'desc':action.desc})
    5     return temp

    我们就以一个字典的形式来保存函数的名称和描述值,然后结合前端的for循环就能拿到所需要的列表

    但是还有一点问题,如果没有设置desc的时候在前端里是拿不到数据的,这时候就要用到反射,

    1 def get_actions_desc(self):
    2     temp = []
    3     for action in self.actions:
    4         if not hasattr(action,'desc'):
    5             action.desc = action.__name__
    6             print(1111111111111111111111)
    7         temp.append({'name':action.__name__,'desc':action.desc})
    8     return temp

    然后在模板里这样做

    <select name="action" id="" style=" 200px; padding: 5px,8px;display: inline-block;">
        <option value="">--------------</option>
        {%for action in view_obj.conf_obj.get_actions_desc%}
        <option value="{{action.name}}">{{action.desc}}</option>
        {%endfor%}
    </select>

    action.desc是action的描述,当有desc点时候就显示为我们指定的字符串,否则就显示为函数名。而action.name直接就是函数名,我们可以拿到这个函数名然后再后台里直接通过反射运行函数。

    获取选中的数据行

    在上面的流程中我们已经拿到了第一个键值对——可以执行选中的函数。下面就要看看怎么拿到第二个键值对——获取选中的数据行了

    在生成checkbox的时候,我们应该给他指定一个name值,还有一个value值,那么在表单在POST的过程中我们就可以通过这个name拿到一个列表,里面是选中的对象的value。为了便于后期的数据库操作,我们可以吧这个value设置的和主键id一样

    1     def select(self,obj=None,get_title=False):
    2         if not get_title:
    3             return mark_safe("<input type='checkbox' name='selected_pk' value='%s'>"%obj.pk)
    4         else:
    5             return mark_safe("<input type='checkbox' class = 'selected'>全选")

    上面是我们视图中生成checkbox的函数,注意第3行里修改以后的部分,加上了name和value

    非常重要的一点

    我们拿到这个选中id组成的列表是通过form标签构成的表单,那么一定要注意这个form的闭合标签的位置,

    <form action="" method="POST">
        {%csrf_token%}
        <select name="action" id="" style=" 200px; padding: 5px,8px;display: inline-block;">
            <option value="">--------------</option>
            {%for action in view_obj.conf_obj.get_actions_desc%}
            <option value="{{action.name}}">{{action.desc}}</option>
            {%endfor%}
        </select>
        <button type="submit">GO</button>
    
        <table class="table table-bordered table-striped">
            <thead>
            </thead>
            <tbody>
            </tbody>
        </table>
    </form>

    由于selectbox是包含在table里的,必须把form的闭合标签放在table后面。这个效果不太好试,图就不截了。

    POST.get和POST.getlist

    注意request.POST.get()方法只能拿到列表中的最后一个元素,这里也是要注意的点。因为选中的对象以后通过POST里的Querydict中的列表存在的

    <QueryDict: {'csrfmiddlewaretoken': ['klNkPOTx4AHP7usgLxBO6zjinSpaOzXmAUgTrXy5qneHQn1vSEkDsX5Zx2j2BHOQ'], 'action': [''], 'selected_pk': ['4', '5']}>

    所以我们必须用getlist方法才能拿到所有的id值。

    后台程序的处理

    ------------恢复内容开始------------

    action功能主要用于批量的操作,主要是结合select标签一起使用,admin控件在不设置的时候默认包含了一个删除所有已选择的对象。

     我们还可以自定义action,就是在自定义的配置类里写一个函数,然后把这个函数名添加到列表里。

    整体思路

     我们主要来看一下当我们点击了go按钮以后发生了什么事情:

    两组键值对

    检查一下点击go按钮以后,其实是发送了一个POST请求的过程,提交请求的时候带了两组键值对,一个是action自己下拉菜单里的值,还有一组就是checkbox对应的值。而先选函数或者先选checkbox是没有影响的,只是最后点击go按钮的时候进行submit提交表单的时候才获取最终的值。

    下拉列表的构造

    下拉列表里的内容要怎么获取呢?在配置累里有个列表,actions = [],默认情况是没有值得

    在自定义配置类的时候,可以自定义一个函数,然后怎么把这个函数的名称显示在下拉列表里呢?

     1 class BookConf(ConfXadmin):
     2     list_display = deepcopy(ConfXadmin.list_display)
     3     list_display.append('price',)
     4     search_fields = ['title','price']
     5 
     6     def patch_init(self,queryset):
     7         print(queryset)
     8 
     9     patch_init.desc = '测试用action'
    10     actions = [patch_init]

    注意最后一行的代码,我们是把函数对象放在列表里的,然后在定义一个函数

    1 def get_actions_name(self):
    2     temp = []
    3     for action in self.actions:
    4         temp.append(action.__name__)
    5 
    6     return temp

    直接把函数名放在一个列表里返回就可以了,然后我们在模板中调用这个函数

    <select name="action" id="" style=" 200px; padding: 5px,8px;display: inline-block;">
        <option value="">--------------</option>
        {%for action in view_obj.conf_obj.get_actions_name%}
        <option value="">{{action}}</option>
        {%endfor%}
    </select>

    这样用一个for循环就能生成需要的列表里

    按自定义要求显示函数名

    admin中是可以通过一个参数short_description来指定显示在下拉列表里的函数的函数名,那么我们怎么实现这个功能呢?

    1 def get_actions_desc(self):
    2     temp = []
    3     for action in self.actions:
    4         temp.append({'name':action.__name__,'desc':action.desc})
    5     return temp

    我们就以一个字典的形式来保存函数的名称和描述值,然后结合前端的for循环就能拿到所需要的列表

    但是还有一点问题,如果没有设置desc的时候在前端里是拿不到数据的,这时候就要用到反射,

    1 def get_actions_desc(self):
    2     temp = []
    3     for action in self.actions:
    4         if not hasattr(action,'desc'):
    5             action.desc = action.__name__
    6             7         temp.append({'name':action.__name__,'desc':action.desc})
    8     return temp

    然后在模板里这样做

    <select name="action" id="" style=" 200px; padding: 5px,8px;display: inline-block;">
        <option value="">--------------</option>
        {%for action in view_obj.conf_obj.get_actions_desc%}
        <option value="{{action.name}}">{{action.desc}}</option>
        {%endfor%}
    </select>

    action.desc是action的描述,当有desc点时候就显示为我们指定的字符串,否则就显示为函数名。而action.name直接就是函数名,我们可以拿到这个函数名然后再后台里直接通过反射运行函数。

    获取选中的数据行

    在上面的流程中我们已经拿到了第一个键值对——可以执行选中的函数。下面就要看看怎么拿到第二个键值对——获取选中的数据行了

    在生成checkbox的时候,我们应该给他指定一个name值,还有一个value值,那么在表单在POST的过程中我们就可以通过这个name拿到一个列表,里面是选中的对象的value。为了便于后期的数据库操作,我们可以吧这个value设置的和主键id一样

    1     def select(self,obj=None,get_title=False):
    2         if not get_title:
    3             return mark_safe("<input type='checkbox' name='selected_pk' value='%s'>"%obj.pk)
    4         else:
    5             return mark_safe("<input type='checkbox' class = 'selected'>全选")

    上面是我们视图中生成checkbox的函数,注意第3行里修改以后的部分,加上了name和value

    非常重要的一点

    我们拿到这个选中id组成的列表是通过form标签构成的表单,那么一定要注意这个form的闭合标签的位置,

    <form action="" method="POST">
        {%csrf_token%}
        <select name="action" id="" style=" 200px; padding: 5px,8px;display: inline-block;">
            <option value="">--------------</option>
            {%for action in view_obj.conf_obj.get_actions_desc%}
            <option value="{{action.name}}">{{action.desc}}</option>
            {%endfor%}
        </select>
        <button type="submit">GO</button>
    
        <table class="table table-bordered table-striped">
            <thead>
            </thead>
            <tbody>
            </tbody>
        </table>
    </form>

    由于selectbox是包含在table里的,必须把form的闭合标签放在table后面。这个效果不太好试,图就不截了。

    POST.get和POST.getlist

    注意request.POST.get()方法只能拿到列表中的最后一个元素,这里也是要注意的点。因为选中的对象以后通过POST里的Querydict中的列表存在的

    <QueryDict: {'csrfmiddlewaretoken': ['klNkPOTx4AHP7usgLxBO6zjinSpaOzXmAUgTrXy5qneHQn1vSEkDsX5Zx2j2BHOQ'], 'action': [''], 'selected_pk': ['4', '5']}>

    所以我们必须用getlist方法才能拿到所有的id值。在拿到了selected_pk以后,我们就可以直接通过filter索引出需要处理的对象交给后台处理。

    后台程序的处理

    这个时候我们就拿到了需要的两个键值对——批量处理的对象id和要用的函数。这里吧list视图里的POST的部分放出来,其他

     1     def list_view(self,request):
     2         if request.method == 'POST':
     3             action_str = request.POST.get('action')
     4             selected_id = request.POST.getlist('selected_pk')
     5 
     6             filter_data = self.model.objects.filter(pk__in = selected_id)
     7 
     8             if hasattr(self,action_str):
     9                 action = getattr(self,action_str)
    10                 ret = action(filter_data)

    这里就是用了一个反射的方法,我们从POST里get到底acction是一个字符串,要通过字符串去执行函数的话当然是用hasattr和getattr了!我们加上了一个判断,其实用处也不大就是防止出错。

    最后一行的ret是因为如果有些自定义的action函数里是可以加上带response的返回值的,后面可以通过加上return ret跳转的别的页面上。

    通用model的默认action

     注意一下admin控件里,所有注册的table都有一个通用的action删除所有选中对象。这时候要怎么处理呢?

     思路就是和获取显示字段列表一样,在Confxadmin类里添加一个函数

     1 def get_actions_list(self):
     2     temp = []
     3     temp.append(ConfXadmin.remove_select_obj)
     4     temp.extend(self.actions)
     5     return temp    
     6 
     7 def get_actions_desc(self):
     8     temp = []
     9     for action in self.get_actions_list():
    10         if not hasattr(action,'desc'):
    11             action.desc = action.__name__
    12         temp.append({'name':action.__name__,'desc':action.desc})
    13     return temp

    如果在自定义里有actions列表,那么就直接拼到后面,否则就是只有默认的批量删除功能。

  • 相关阅读:
    Mayan游戏 (codevs 1136)题解
    虫食算 (codevs 1064)题解
    靶形数独 (codevs 1174)题解
    黑白棋游戏 (codevs 2743)题解
    神经网络 (codevs 1088) 题解
    The Rotation Game (POJ 2286) 题解
    倒水问题 (codevs 1226) 题解
    银河英雄传说 (codevs 1540) 题解
    生日蛋糕 (codevs 1710) 题解
    第一章 1.11 高阶函数
  • 原文地址:https://www.cnblogs.com/yinsedeyinse/p/13526974.html
Copyright © 2011-2022 走看看