一、先看下django的admin是如何做搜索功能的
配置一个search_fields的列表就可以实现搜索的功能
class testbook(admin.ModelAdmin): # 第一步,定义一个函数,必须要接受三个参数 def test_action(self,request,queryset): """ :param request: :param queryset:这个就是需要批量操作的queryset对象 :return: """ print(queryset) # 第二步,为这个函数对象赋值一个新的属性 test_action.short_description = "测试批量操作的函数" # 第三步,将函数对象添加到actions这个列表中 actions = [test_action] list_filter = ["auther","publist"] search_fields = ["auther","title"]
看下页面的效果,这里就可以通过auther或者title进行搜索了
二、下面看下我们的stark组件是如何做搜索的
1、首先我们也在自己的配置类里定义一个search_field的搜索字段
class bookclass(stark.Starkclass): list_display = ["id","title","price","auther","publish"] list_display_links = ["id","price","auther"] search_fields = ["title","price"] def test_action(self,request,queryset): print(queryset,) actions = [test_action] # test_action.__name__ = "测试批量操作的函数" test_action.short_description = "测试批量操作的函数" modelformclass = mybookmodelform
2、同样,我们还需要在父类中定义一个search_field字段,为了防止客户未定义search_field字段和报错
class Starkclass(object): list_display = ['__str__'] list_display_links = [] search_fields = [] modelformclass = None actions = [] list_filter = []
3、然后我们看下具体的代码
这里我们先简单的说一下思路,我们默认会显示所有的数据,那么,如果我们加了一个搜索的字段,那么我们中就加一个参数,这个参数的k就是search,v就是我们输入的值,
这样后端拿到搜索的字段后,就可以使用Q查询做or的匹配,然后显示出过滤后的信息就可以了
def list_url(self,request): import importlib if request.method == "POST": func = request.POST.get("func") action_list = request.POST.getlist("selectpk") action_func = getattr(self,func) queryset = self.model.objects.filter(id__in=action_list) action_func(request,queryset) new_list = self.create_new_display() q_obj = self.get_search(request) q_filter_obj = self.get_filter(request) if q_obj and q_filter_obj: new_data_list = self.model.objects.all().filter(q_obj).filter(q_filter_obj) elif q_obj and not q_filter_obj: new_data_list = self.model.objects.all().filter(q_obj) elif not q_obj and q_filter_obj: new_data_list = self.model.objects.all().filter(q_filter_obj) else: new_data_list = self.model.objects.all() showlist = Showlist(self, request, new_list,new_data_list)
通过get_search函数去获取过滤的信息
4、下面我们看下get_search函数的代码
def get_search(self,request): from django.db.models import Q search_str = request.GET.get("search", None) if search_str: if self.search_fields: q_obj = Q() q_obj.connector = "or" for field in self.search_fields: q_obj.children.append((field + "__icontains", search_str)) return q_obj else: return None else: return None
获取到search的字段,然后做q查询,最终返回一个q对象
5、list_url函数拿到返回的Q对象,然后做过滤,将过滤后的信息传递给showlist这个类,在来显示
def list_url(self,request): import importlib if request.method == "POST": func = request.POST.get("func") action_list = request.POST.getlist("selectpk") action_func = getattr(self,func) queryset = self.model.objects.filter(id__in=action_list) action_func(request,queryset) new_list = self.create_new_display() q_obj = self.get_search(request) q_filter_obj = self.get_filter(request) if q_obj and q_filter_obj: new_data_list = self.model.objects.all().filter(q_obj).filter(q_filter_obj) elif q_obj and not q_filter_obj: new_data_list = self.model.objects.all().filter(q_obj) elif not q_obj and q_filter_obj: new_data_list = self.model.objects.all().filter(q_filter_obj) else: new_data_list = self.model.objects.all() showlist = Showlist(self, request, new_list,new_data_list) title_list = showlist.get_header() data_list = showlist.get_body() page_str = showlist.get_page() action_str = showlist.get_actions() get_filter = showlist.get_filter_link_tag() return render(request,"list_view.html",{"data_list":data_list,"title_list":title_list,"page_str":page_str,"search_fields":self.search_fields,"action_str":action_str, "get_filter":get_filter })
重点是看这里
然后我们在看下showlist的类
class Showlist(object): def __init__(self,config,request,new_list,new_data_list): self.config = config self.request = request self.new_list = new_list self.new_data_list = new_data_list # 分页显示 count = self.new_data_list.count() current_page = int(request.GET.get("p",1)) per_page_num = 3 base_url = request.path_info parms = request.GET self.page_str = page.page_helper(count=count,current_page=current_page,per_page_num=per_page_num,base_url=base_url,parms=parms)
def get_body(self): from django.db.models import Q new_list = self.new_list data_list_obj = self.new_data_list[self.page_str.db_start() - 1:self.page_str.db_end() - 1] data_list = [] for obj in data_list_obj: temp_list = [] for i in new_list: if not callable(i): if self.config.list_display_links: if i in self.config.list_display_links: # i_obj = obj._meta.get_field(i) # print(type(i_obj),"i_obj",i) from django.db.models.fields.related import ManyToManyField i_obj = obj._meta.get_field(i) if isinstance(i_obj,(ManyToManyField,)): many = getattr(obj, i) many_query_set = many.all() temp = "" for o in many_query_set: temp = temp + str(o) + "&" temp = temp.rstrip("&") else: temp = getattr(obj,i) app_name = obj._meta.app_label model_name = obj._meta.model_name edit_path = "/stark/{app}/{model}/edit/{eid}".format(app=app_name, model=model_name, eid=obj.id) temp = mark_safe("<a href='{path}'>{link}</a>".format(link=temp,path=edit_path)) else: from django.db.models.fields.related import ManyToManyField i_obj = obj._meta.get_field(i) if isinstance(i_obj,(ManyToManyField,)): many = getattr(obj, i) many_query_set = many.all() temp = "" for o in many_query_set: temp = temp + str(o) + "&" temp = temp.rstrip("&") else: temp = getattr(obj, i) else: temp = getattr(obj,i) else: temp = i(self,obj) temp_list.append(temp) data_list.append(temp_list) return data_list
返回过滤后的数据
6、最后我们看下页面的代码,如果有search_field字段,页面才显示,如果没有则不会显示
{% if search_fields %} <form class="pull-right" method="get"> <input type="text" name="search" placeholder="搜索"><input type="submit" value="搜索"> </form> {% endif %}
这里我们用form表单发get请求,进行搜索,之间我们都是用form表单发送post请求,其实form表单也可以发get请求,这是我们不常用而已
7、页面效果如下