组合搜索组件文档

组合搜索组件

1. 先展示一下使用效果:

组合搜索组件文档

2. 使用方法

  • 第一步: 在views.py中配置和传参
search_group = NbSearchGroup(     request,     models.TransactionRecord,  # 传入表     Option('charge_type'),  # 传入choice字段名 ) 

组合搜索组件文档

  • 第二步: 添加查询条件
# 查询条件 .filter(**search_group.get_condition) queryset = models.TransactionRecord.objects.filter(q).filter(**search_group.get_condition).filter(     customer_id=request.user_obj.id, active=1).order_by(     '-id') 
  • 第三步: 向html中传递参数
context = {     'show_data': pager.show_data,     'pager_string': pager.html(),     'keyword': keyword,     "search_group": search_group  # 这是需要添加的 } return render(request, 'transaction_list.html', context) 

组合搜索组件文档

  • 第四步: 导入html search_group.html
{% if search_group.get_row_list %}     <div class="panel panel-default">         <div class="panel-heading">             <i class="fa fa-filter" aria-hidden="true"></i> 快速筛选         </div>         <div class="panel-body">             <div class="search-group">                 {% for row in search_group.get_row_list %}                     <div class="row">                         {% for obj in row %}                             {{ obj|safe }}                         {% endfor %}                     </div>                 {% endfor %}             </div>         </div>     </div> {% endif %} 
  • 第五步: 导入css(最好放到static静态文件中) search_group.css
.search-group {     padding: 5px 10px; }  .search-group .row .whole {     width: 60px;     float: left;     display: inline-block;     padding: 5px 0 5px 8px;     margin: 3px;     font-weight: bold;     text-align: right;  }  .search-group .row .others {     padding-left: 80px; }  .search-group .row a {     display: inline-block;     padding: 5px 8px;     margin: 3px;     border: 1px solid #d4d4d4;  }  .search-group .row a {     display: inline-block;     padding: 5px 8px;     margin: 3px;     border: 1px solid #d4d4d4; }  .search-group a.active {     color: #fff;     background-color: #337ab7;     border-color: #2e6da4; } 
  • 第六步: 导入核心代码(源码)group.py
# -*- encoding:utf-8 -*- # @time: 2023/4/14 21:03 # @author: Maxs_hu from django.db.models import ForeignKey, ManyToManyField   class SearchGroupRow(object):     def __init__(self, title, queryset_or_tuple, option, query_dict):         """         :param title: 组合搜索的列名称         :param queryset_or_tuple: 组合搜索关联获取到的数据         :param option: 配置         :param query_dict: request.GET         """         self.title = title         self.queryset_or_tuple = queryset_or_tuple         self.option = option         self.query_dict = query_dict      def __iter__(self):         yield '<div class="whole">'         yield self.title         yield '</div>'         yield '<div class="others">'         total_query_dict = self.query_dict.copy()         total_query_dict._mutable = True          origin_value_list = self.query_dict.getlist(self.option.field)         if not origin_value_list:             yield "<a class='active' href='?%s'>全部</a>" % total_query_dict.urlencode()         else:             total_query_dict.pop(self.option.field)             yield "<a href='?%s'>全部</a>" % total_query_dict.urlencode()          for item in self.queryset_or_tuple:             text = self.option.get_text(item)             value = str(self.option.get_value(item))             query_dict = self.query_dict.copy()             query_dict._mutable = True              if not self.option.is_multi:                 query_dict[self.option.field] = value                 if value in origin_value_list:                     query_dict.pop(self.option.field)                     yield "<a class='active' href='?%s'>%s</a>" % (query_dict.urlencode(), text)                 else:                     yield "<a href='?%s'>%s</a>" % (query_dict.urlencode(), text)             else:                 # {'gender':['1','2']}                 multi_value_list = query_dict.getlist(self.option.field)                 if value in multi_value_list:                     multi_value_list.remove(value)                     query_dict.setlist(self.option.field, multi_value_list)                     yield "<a class='active' href='?%s'>%s</a>" % (query_dict.urlencode(), text)                 else:                     multi_value_list.append(value)                     query_dict.setlist(self.option.field, multi_value_list)                     yield "<a href='?%s'>%s</a>" % (query_dict.urlencode(), text)          yield '</div>'   class Option(object):     def __init__(self, field, is_condition=True, is_multi=False, db_condition=None, text_func=None, value_func=None):         """         :param field: 组合搜索关联的字段         :param is_multi: 是否支持多选         :param db_condition: 数据库关联查询时的条件         :param text_func: 此函数用于显示组合搜索按钮页面文本         :param value_func: 此函数用于显示组合搜索按钮值         """         self.field = field         self.is_condition = is_condition         self.is_multi = is_multi         if not db_condition:             db_condition = {}         self.db_condition = db_condition         self.text_func = text_func         self.value_func = value_func          self.is_choice = False      def get_db_condition(self, request, *args, **kwargs):         return self.db_condition      def get_queryset_or_tuple(self, model_class, request, *args, **kwargs):         """         根据字段去获取数据库关联的数据         :return:         """         # 根据gender或depart字符串,去自己对应的Model类中找到 字段对象         field_object = model_class._meta.get_field(self.field)         title = field_object.verbose_name         # 获取关联数据         if isinstance(field_object, ForeignKey) or isinstance(field_object, ManyToManyField):             # FK和M2M,应该去获取其关联表中的数据: QuerySet             db_condition = self.get_db_condition(request, *args, **kwargs)             return SearchGroupRow(title,                                   field_object.remote_field.model.objects.filter(**db_condition),                                   self,                                   request.GET)         else:             # 获取choice中的数据:元组             self.is_choice = True             return SearchGroupRow(title, field_object.choices, self, request.GET)      def get_text(self, field_object):         """         获取文本函数         :param field_object:         :return:         """         if self.text_func:             return self.text_func(field_object)          if self.is_choice:             return field_object[1]          return str(field_object)      def get_value(self, field_object):         if self.value_func:             return self.value_func(field_object)          if self.is_choice:             return field_object[0]          return field_object.pk      def get_search_condition(self, request):         if not self.is_condition:             return None         if self.is_multi:             values_list = request.GET.getlist(self.field)  # tags=[1,2]             if not values_list:                 return None             return '%s__in' % self.field, values_list         else:             value = request.GET.get(self.field)  # tags=[1,2]             if not value:                 return None             return self.field, value   class NbSearchGroup(object):     def __init__(self, request, model_class, *options):         self.request = request         self.model_class = model_class         self.options = options      def get_row_list(self):         row_list = []         for option_object in self.options:             row = option_object.get_queryset_or_tuple(self.model_class, self.request)             row_list.append(row)         return row_list      @property     def get_condition(self):         """         获取组合搜索的条件         :param request:         :return:         """         condition = {}         # ?depart=1&gender=2&page=123&q=999         for option in self.options:             key_and_value = option.get_search_condition(self.request)             if not key_and_value:                 continue             key, value = key_and_value             condition[key] = value          return condition 

3. 分享源码实现和封装

from django.db.models import ForeignKey, ManyToManyField   class SearchGroupRow(object):     def __init__(self, title, queryset_or_tuple, option, query_dict):         """         :param title: 组合搜索的列名称         :param queryset_or_tuple: 组合搜索关联获取到的数据         :param option: 配置         :param query_dict: request.GET         """         self.title = title         self.queryset_or_tuple = queryset_or_tuple         self.option = option         self.query_dict = query_dict      def __iter__(self):         yield '<div class="whole">'         yield self.title         yield '</div>'         yield '<div class="others">'         total_query_dict = self.query_dict.copy()         total_query_dict._mutable = True          origin_value_list = self.query_dict.getlist(self.option.field)         if not origin_value_list:             yield "<a class='active' href='?%s'>全部</a>" % total_query_dict.urlencode()         else:             total_query_dict.pop(self.option.field)             yield "<a href='?%s'>全部</a>" % total_query_dict.urlencode()          for item in self.queryset_or_tuple:             text = self.option.get_text(item)             value = str(self.option.get_value(item))             query_dict = self.query_dict.copy()             query_dict._mutable = True              if not self.option.is_multi:                 query_dict[self.option.field] = value                 if value in origin_value_list:                     query_dict.pop(self.option.field)                     yield "<a class='active' href='?%s'>%s</a>" % (query_dict.urlencode(), text)                 else:                     yield "<a href='?%s'>%s</a>" % (query_dict.urlencode(), text)             else:                 # {'gender':['1','2']}                 multi_value_list = query_dict.getlist(self.option.field)                 if value in multi_value_list:                     multi_value_list.remove(value)                     query_dict.setlist(self.option.field, multi_value_list)                     yield "<a class='active' href='?%s'>%s</a>" % (query_dict.urlencode(), text)                 else:                     multi_value_list.append(value)                     query_dict.setlist(self.option.field, multi_value_list)                     yield "<a href='?%s'>%s</a>" % (query_dict.urlencode(), text)          yield '</div>'   class Option(object):     def __init__(self, field, is_condition=True, is_multi=False, db_condition=None, text_func=None, value_func=None):         """         :param field: 组合搜索关联的字段         :param is_multi: 是否支持多选         :param db_condition: 数据库关联查询时的条件         :param text_func: 此函数用于显示组合搜索按钮页面文本         :param value_func: 此函数用于显示组合搜索按钮值         """         self.field = field         self.is_condition = is_condition         self.is_multi = is_multi         if not db_condition:             db_condition = {}         self.db_condition = db_condition         self.text_func = text_func         self.value_func = value_func          self.is_choice = False      def get_db_condition(self, request, *args, **kwargs):         return self.db_condition      def get_queryset_or_tuple(self, model_class, request, *args, **kwargs):         """         根据字段去获取数据库关联的数据         :return:         """         # 根据gender或depart字符串,去自己对应的Model类中找到 字段对象         field_object = model_class._meta.get_field(self.field)         title = field_object.verbose_name         # 获取关联数据         if isinstance(field_object, ForeignKey) or isinstance(field_object, ManyToManyField):             # FK和M2M,应该去获取其关联表中的数据: QuerySet             db_condition = self.get_db_condition(request, *args, **kwargs)             return SearchGroupRow(title,                                   field_object.remote_field.model.objects.filter(**db_condition),                                   self,                                   request.GET)         else:             # 获取choice中的数据:元组             self.is_choice = True             return SearchGroupRow(title, field_object.choices, self, request.GET)      def get_text(self, field_object):         """         获取文本函数         :param field_object:         :return:         """         if self.text_func:             return self.text_func(field_object)          if self.is_choice:             return field_object[1]          return str(field_object)      def get_value(self, field_object):         if self.value_func:             return self.value_func(field_object)          if self.is_choice:             return field_object[0]          return field_object.pk      def get_search_condition(self, request):         if not self.is_condition:             return None         if self.is_multi:             values_list = request.GET.getlist(self.field)  # tags=[1,2]             if not values_list:                 return None             return '%s__in' % self.field, values_list         else:             value = request.GET.get(self.field)  # tags=[1,2]             if not value:                 return None             return self.field, value 

4. 分享案例

组合搜索组件文档

优点:

  1. 可根据传入的字段名读取表中choice并展示和实现对应的筛选功能
  2. 大多数项目可以应用上
  3. 思路(django中admin的源码以及stark组件)
发表评论

评论已关闭。

相关文章