stark组件之多级过滤

时间:2023-04-27 09:08:44

  一、引子

  在我们浏览很多页面时,会发现一般情况下都有一个分类的功能,而且还是多个类别同时控制,这就是多级过滤。如下图:

stark组件之多级过滤

  一行代表一个类别,第一行就是展示了所有的出版社,选中后就会以出版社分类,第二行就是以作者分类,当都选择了,就共同控制。此时选中了‘人民出版社’和‘余华’,数据就会以这两者共同过滤,当我们选择作家出版社时,人民出版社就会被取消,当我们选择某一类的all时,这一类的其他被选中的就会被取消。

  首先在starkmodel有个filter_list列表,这个是包含总共有哪些类别。

  二、代码

  从要实现的效果来看,除了每行的第一个,其他所有的都应该是a标签。如果是单级过滤的话,每个a标签的路径可以写死。但现在是多级过滤,a标签的路径就只能是动态的,所谓的动态,无非是在自己的固有过滤条件上再加上已经选中的其他类别的过滤条件。效果是这样的。当我们第一次进入页面时,没有选中任何过滤条件,每个a标签就是自己的固有过滤条件;当我们点击‘人民出版社’时,就发送了请求,此时后台就要重构a标签的路径了,出版社下的a标签不用改动,作者下的a标签就要在自己的固有过滤条件下加上本次请求的过滤条件,这样才能在点击‘余华’的时候既有‘人民出版社’,还会有‘余华’两个过滤条件。

  每一行的all就是把跟自己属于同一类的过滤条件给去掉就行了。

  sites.py:

class Show(object):
def show_filter(self):
filter_dict={}
for field in self.config_obj.filter_list: #循环配置类的filter_list,取出需要进行分类的字段
filter_list = []
params=copy.deepcopy(self.request.GET) #params是本次请求的条件
if params.get('page'): #这是把页码的过滤条件给去了
params.pop('page')
if params.get(field): #这是把当前字段的过滤条件给去了,因为params要给all使用
params.pop(field)
filter_list.append('<a class="btn-sm btn-default" href="?%s">all</a>'%params.urlencode()) #这是构造每一行的all标签
field_obj=self.config_obj.model._meta.get_field(field) #filter_list列表里面存放的是字符串,通过这方法拿到字符串对应的字段对象
if field_obj.choices: #字段对象存在是choices,直接拿就行
data=field_obj.choices #此时得到的数据是元祖套元祖类型的
else: #该字段对象不存在choices
rel_model=field_obj.remote_field.model #拿到该字段对象对应的模型类
data=rel_model.objects.all() #得到的数据就是模型类的所有对象
for obj in data:
if type(obj) == tuple: #如果是元祖类型,直接解包
pk,text=obj
else: #如果不是元祖类型,说明是一个对象,我们拿到对象的pk值和名字就行
pk,text=obj.pk,obj
params[field]=pk #我们把pk值放入到params中去
if self.request.GET.get(field)==str(pk): #构造all后面的a标签
filter_list.append('<a class="btn-sm btn-default active" href="?%s">%s</a>'%(params.urlencode(),text))
else:
filter_list.append('<a class="btn-sm btn-default" href="?%s">%s</a>'%(params.urlencode(), text))
filter_dict[field]=filter_list
return filter_dict -------------------------------得到的filter_dict-----------------------------------------------------------------

{'publish': ['<a class="btn-sm btn-default" href="?author=2">all</a>', '<a class="btn-sm btn-default active" href="?author=2&publish=1">人民出版社</a>', '<a class="btn-sm btn-default" href="?author=2&publish=2">作家出版社</a>', '<a class="btn-sm btn-default" href="?author=2&publish=3">天天出版社</a>']}
{'publish': ['<a class="btn-sm btn-default" href="?author=2">all</a>', '<a class="btn-sm btn-default active" href="?author=2&publish=1">人民出版社</a>', '<a class="btn-sm btn-default" href="?author=2&publish=2">作家出版社</a>', '<a class="btn-sm btn-default" href="?author=2&publish=3">天天出版社</a>'], 'author': ['<a class="btn-sm btn-default" href="?publish=1">all</a>', '<a class="btn-sm btn-default" href="?publish=1&author=1">路遥</a>', '<a class="btn-sm btn-default active" href="?publish=1&author=2">余华</a>', '<a class="btn-sm btn-default" href="?publish=1&author=3">杨绛</a>']}

  前端页面代码:

<div class="filter">
{% if show.config_obj.filter_list %}
{% for field,obj_list in show.show_filter.items %}
<span class="btn btn-success">{{ field }}</span>
{% for obj in obj_list %}
{{ obj|safe }}
{% endfor %}
<br>
{% endfor %}
{% endif %}
</div>