一、先看下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、页面效果如下

 

 

posted on 2018-12-18 06:53  bainianminguo  阅读(229)  评论(0编辑  收藏  举报