在python web开发中,如何通过点击checkbox单选框来确定路由地址,然后如何根据路由地址来筛选出对应点击的内容。

涉及知识点:

  1. 迭代器   2. 根据点击的单选框设计URL参数   3. 根据URL参数过滤数据并展示

  首先,我们设计一个迭代器,迭代器可以返回a标签单选框,将这些a标签单选框传给前端页面,前端页面循环根据迭代器生成的迭代器对象,即可显示出a标签单选框。在渲染页面的时候,我们从数据库中拿到要展示的choice类型字段的choice数据,构造成下面这种形式。将这个数据传递给前端,CheckFilter即为一个迭代器。

filter_list = [
            {'title': "问题类型", 'filter': CheckFilter('issues_type', project_issue_type, request)},
            {'title': "状态", 'filter': CheckFilter('status', models.Issues.status_choices, request)},
            {'title': "优先级", 'filter': CheckFilter('priority', models.Issues.priority_choices, request)},
        ]

  在迭代器中,我们做这么几件事情:首先我们将要使用的数据初始化一下,data_list是数据库中的choice类型字段,是元组里面套元组的格式,然后定义__iter__方法,在这个方法里面,我们首先循环我们拿到的data_list,分别定义key和text,然后得到当前请求的URL中的参数,定义为value_list,使用request.GET.getlist()方法;每次循环的时候,判断key是否在value_list中,如果在就将value_list中的key值移除,如果不在就将这次循环的key值添加到value_list中。每次循环在构造好了value_list数据之后,我们通过request.GET获取URL中的参数和参数值,得到的是QueryDict类型数据,将这个QueryDict数据通过urldecode()方法解析成路由参数的形式,再通过request.path_info获取主路由,将参数和路由在一起拼接成一个完整路由。接着我们够造a标签单选框,里面的路由即为构造好的路由。如果要为点击的单选框添加checked形式怎么办?我们在判断key是否在value_list中去够造每次循环需要的value_list的时候,我们可以这样定义:如果单次循环的key在value_list中,那么我们定义一个check="checked",如果不在那么check=“”,然后再够造a标签的时候将check添加到a标签中,通过mark_safe的方式生成a标签,然后yield这个a标签。在后端利用这个迭代器生成一个迭代器对象,在前端利用这个迭代器对象进行渲染a标签单选框

  代码如下:

class CheckFilter(object):
    def __init__(self, name, data_list, request):
        self.name = name
        self.data_list = data_list
        self.request = request

    def __iter__(self):
        for item in self.data_list:
            key = str(item[0])
            text = item[1]
            ck = ""
            # 如果当前用户请求的URL中参数名和当前循环key相等
            value_list = self.request.GET.getlist(self.name) # ['2', '3', '4']
            #print(value_list)
            #如果url中携带的参数值在数据库中,就移除,不在就添加
            if key in value_list:
                ck = 'checked'
                value_list.remove(key)
            else:
                value_list.append(key)
            #print(key,text,value_list)


            # 为自己生成URL
            # 在当前URL的基础上去增加一项
            # status=1&age=19
            from django.http import QueryDict
            query_dict = self.request.GET.copy() #<QueryDict: {'status': ['2', '3', '4']}>
            query_dict._mutable = True
            query_dict.setlist(self.name, value_list)
            if 'page' in query_dict:
                query_dict.pop('page')

            param_url = query_dict.urlencode()
            #print(param_url)
            #print("*" * 10)
            if param_url:
                url = "{}?{}".format(self.request.path_info, param_url)  # status=1&status=2&status=3&xx=1
            else:
                url = self.request.path_info

            tpl = '<a class="cell" href="{url}"><input type="checkbox" {ck} /><label>{text}</label></a>'
            html = tpl.format(url=url, ck=ck, text=text)
            yield mark_safe(html)

  这里有一点我个人认为比较难理解的地方,就是在够造value_list的时候的方法。逻辑是这样的:第一次我们进入的页面上的URL没有任何参数,每一个a标签单选框都是自己本身的路由,每次在循环够造新的value_list的时候,从URL获取的value_list是空,所以我们每次都将循环的key添加到value_list中,通过这个新生成的value_list创建a标签的时候就只有一个参数。当我们点击了一个a标签,页面刷新,我们访问的URL中有一个参数,我们再进行循环,假设第一次循环的key在从URL获取的value_list中,那么我们将value_list中的key值移除,此次循环生成的a标签的路由就是主路由,并且加上了checked属性,第二次循环的时候,此次的key不在从URL获取的value_list中,我们将这次的key添加到value_list中,生成新的value_list,利用这个新的value_list生成的a标签中有两个参数,当我们点击这个a标签单选框的时候,我们访问的URL就有两个参数,接下来的循环一样,剩余的每个key对应的a标签都有两个参数。当我们再点击一个新的单选框的时候,即有两个单选框被选中,那么我们点击访问的URL中有两个参数,我们第一次循环的key在从URL获取的value_list中,将其移除,此时value_list中只有一个参数,被选中的单选框生成的a标签的路由中只有一个参数,参数值是另一个被点击的单选框对应的参数,当我们在页面刷新之后再点击这个单选框,这个单选框不被选中,只有一个单选框被选中,所以只有一个参数。而此时另外的未被选择的单选框对应的参数有三个,因为在循环生成a标签的时候,key不在从URL获得的value_list中,我们进行追加,三个参数分别是已经点击的两个单选框参数和本身。点击多个单选框的时候,逻辑也是一样。每次点击单选框之后,每个单选框对应的a标签的URL参数都不一样。

  如何根据URL参数来过滤数据并展示呢?我们需要根据数据库中的字段定义出name = {‘字段名__in’:[ ]} 的字典,[ ]是choice类型字段的所对应的数字,然后在通过orm筛选数据得时候通过.filter(name) 的方式来筛选出需要的数据。示例代码如下:

def issues(request, project_id):
    if request.method == 'GET':
        # 根据URL做筛选,筛选条件(根据用户通过GET传过来的参数实现)
        allow_filter_name = ['issues_type', 'status', 'priority', 'assign', 'attention']
        condition = {}
        for name in allow_filter_name:
            params_list = request.GET.getlist(name)
            if not params_list:
                continue
            condition['{}__in'.format(name)] = params_list
        """
        condition = {'issues_type__in':[1,2],'status__in':[1,2,3]}
        """
        # 根据URL参数过滤数据,再分页展示数据
        queryset = models.Issues.objects.filter(project_id=project_id).filter(**condition)
        ......
原文地址:https://www.cnblogs.com/fangyu-blog/p/14546012.html