Django开发教程:实现全局搜索功能

2,256 阅读4分钟

大家好,我是梓栋! 有粉丝要实现全局搜索功能不知道怎么实现,让我出一套教程,本来今天很忙的,但为了家人们,我也要挤时间出来肝一篇教程啊!

image-20210718162012355

废话不多说,下面开始讲! 本教程是基于图书管理系统实现的全局搜索功能。比如在搜索框里搜索Python编程,就会出现该图书的相关信息,如下图所示,接下来我们来实现一下。

image-20210718162046599

image-20210718162101195

一、全局搜索功能实现

1.实现的大致流程图,如下图:

image-20210718162918522

2. 路由函数url.py中写如下代码

path("search/", views.search,name="search"),

3.绘制搜索框,效果图如下:

img

html代码如下 :

<li class="nav-item">
                 <form action="{% url "librarian:search" %}" method="post">
                       {% csrf_token %}
                        <div class="card-body">
                           <div class="input-group">
                               <div class="input-group-prepend">
                                   <span class="input-group-text"><i class="zmdi zmdi-book"></i></span>
                               </div>
                               <input type="text" name="search_keywords" class="form-control"/>
•
                               <div class="input-group-append">
                                   <button class="btn-outline-facebook"><i
                                           class="fa fa-search"></i></button>
•
•
                                </div>
                            </div>
                        </div>
                    </form>
                </li>

4.视图函数views.py中要实现的功能

在视图函数中主要实现的QuerySet查询功能,从数据库中搜索到对象后返回到前端页面。如果还有同学对QuerySet不是很熟练的话,可以看看这篇 Django开发教程:QuerySet概念及操作

(1)从前端中获取用户输入的关键字

search_keywords = request.POST.get("search_keywords", "")

(2)根据关键字从数据库中查询数据

if search_keywords:
    books_obj_list = models.Books.objects.filter(
    Q(book_name=search_keywords) | Q(author=search_keywords))  # 根据关键词搜索数据库记录,
    publishers_obj_list = models.Publisher.objects.filter(
    Q(name=search_keywords) | Q(address=search_keywords))

上面的方法中,我们用到了Q查询,filter()等方法中的关键字参数查询都是一起进行’and’的操作,如果需要执行更复杂的查询(例如OR语句),我们可以使用Q对象。

Q对象和 |(或)、&(与)、()(括号)、~(非) 进行联合使用

注意:Q对象和关键字混合使用的时候,关键字需要写在最后。

其实上面的代码实现的是精准查询,如果想实现模糊查询,可以使用icontains(查询时不区分大小写)进行搜索查询。

if search_keywords:
      books_obj_list = models.Books.objects.filter(
      Q(book_name__icontains=search_keywords) | Q(author__icontains=search_keywords))  # 根据关键词搜索数据库记录,icontains是不区分大小写
      publishers_obj_list = models.Publisher.objects.filter(
                  Q(name__icontains=search_keywords) | Q(address=search_keywords))

(3)判断查询结果,用来控制前端页面绘制。

这里主要查询图书和出版社两个数据库表中的数据,如果能从图书数据表查询到数据就给前端页面返回True,让其绘制图书查询结果,出版社亦然。

# 如果能查询到,前端显示图书查询结果
if len(books_obj_list) != 0:  
        books_search_result = True
 # 如果能查到,前端显示出版社查询结果
  elif len(publishers_obj_list) != 0: 
        publishers_search_result = True
  else:
        error_msg = "没有查询到结果,请重新输入"

全部代码如下:

def search(request):
    # 要前端中获取用户输入的关键字
    search_keywords = request.POST.get("search_keywords", "")
    # print(search_keywords)
    if search_keywords:
        books_obj_list = models.Books.objects.filter(
            Q(book_name__icontains=search_keywords) | Q(author__icontains=search_keywords))  # 根据关键词搜索数据库记录,icontains是不区分大小写
        publishers_obj_list = models.Publisher.objects.filter(
            Q(name__icontains=search_keywords) | Q(address=search_keywords))
        # 判断查询结果,用来控制前端页面绘制
        if len(books_obj_list) != 0:  # 如果能查询到,前端显示图书查询结果
            books_search_result = True
        elif len(publishers_obj_list) != 0:  # 如果能查到,前端显示出版社查询结果
            publishers_search_result = True
        else:
            error_msg = "没有查询到结果,请重新输入"
    else:
        error_msg = "你输入的信息错误,请重新出入"
    return render(request, "search_result.html", locals())

(4)绘制查询结果页面

根据视图函数的传到前端的值来绘制页面。

  • if books_search_result == True 成立,绘制图书查询结果页面
  • elif publishers_search_result == True成立,绘制出版社查询结果页面

image-20210718162654277

查询结果页面的全部代码如下:

{% if books_search_result == True %}
        <div class="content-wrapper">
            <div class="container-fluid">
                <div class="row">
                    <div class="col-lg-12">
                        <div class="card gradient-forest">
                            <div class="card gradient-forest"><h4 style="color:red">图书查询结果</h4></div>
                            <div class="card-body text-center p-5">
                                <div class="table-responsive">
                                    <div id="default-datatable_wrapper"
                                         class="dataTables_wrapper container-fluid dt-bootstrap4"><div class="row">
                                            <div class="col-sm-12">
                                                <table class="table table-dark table-striped shadow-dark"
                                                       role="grid" aria-describedby="default-datatable_info">
                                                    <thead>
                                                    <tr role="row">
                                                        <th class="sorting_asc" tabindex="0"
                                                            aria-controls="default-datatable" rowspan="1" colspan="1"
                                                            aria-sort="ascending"
                                                            aria-label="Name: activate to sort column descending"
                                                            style="width: 50px;
                                                    font-size:17px">
                                                            <p>图书编号</p>
                                                        </th>
                                                        <th class="sorting" tabindex="0"
                                                            aria-controls="default-datatable"
                                                            rowspan="1" colspan="1"
                                                            aria-label="Position: activate to sort column ascending"
                                                            style="width: 100px;font-size:17px"><p>图书名称</p>
                                                        </th>
                                                        <th class="sorting" tabindex="0"
                                                            aria-controls="default-datatable"
                                                            rowspan="1" colspan="1"
                                                            aria-label="Office: activate to sort column ascending"
                                                            style="width: 100px;font-size:17px"><p>图书图片</p>
                                                        </th>
                                                        <th class="sorting" tabindex="0"
                                                            aria-controls="default-datatable"
                                                            rowspan="1" colspan="1"
                                                            aria-label="Office: activate to sort column ascending"
                                                            style="width: 100px;font-size:17px"><p>图书类型</p>
                                                        </th>
                                                        <th class="sorting" tabindex="0"
                                                            aria-controls="default-datatable"
                                                            rowspan="1" colspan="1"
                                                            aria-label="Office: activate to sort column ascending"
                                                            style="width: 100px;font-size:17px"><p>作者</p>
                                                        </th>
                                                        <th class="sorting" tabindex="0"
                                                            aria-controls="default-datatable"
                                                            rowspan="1" colspan="1"
                                                            aria-label="Office: activate to sort column ascending"
                                                            style="width: 100px;font-size:17px"><p>图书价格</p>
                                                        </th>
                                                        <th class="sorting" tabindex="0"
                                                            aria-controls="default-datatable"
                                                            rowspan="1" colspan="1"
                                                            aria-label="Office: activate to sort column ascending"
                                                            style="width: 100px;font-size:17px"><p>图书评分</p>
                                                        </th>
                                                        <th class="sorting" tabindex="0"
                                                            aria-controls="default-datatable"
                                                            rowspan="1" colspan="1"
                                                            aria-label="Office: activate to sort column ascending"
                                                            style="width: 101px;font-size:17px"><p>图书简介</p>
                                                        </th>
                                                        <th class="sorting" tabindex="0"
                                                            aria-controls="default-datatable"
                                                            rowspan="1" colspan="1"
                                                            aria-label="Office: activate to sort column ascending"
                                                            style="width: 100px;font-size:17px"><p>图书销量</p>
                                                        </th>
                                                        <th class="sorting" tabindex="0"
                                                            aria-controls="default-datatable"
                                                            rowspan="1" colspan="1"
                                                            aria-label="Office: activate to sort column ascending"
                                                            style="width: 100px;font-size:17px"><p>图书评论量</p>
                                                        </th>
                                                        <th class="sorting" tabindex="0"
                                                            aria-controls="default-datatable"
                                                            rowspan="1" colspan="1"
                                                            aria-label="Office: activate to sort column ascending"
                                                            style="width: 100px;font-size:17px"><p>图书库存</p>
                                                        </th>
                                                        <th class="sorting" tabindex="0"
                                                            aria-controls="default-datatable"
                                                            rowspan="1" colspan="1"
                                                            aria-label="Office: activate to sort column ascending"
                                                            style="width: 100px;font-size:17px"><p>出版社</p>
                                                        </th>
                                                    </tr>
                                                    </thead>
                                                    <tbody>
                                                    {% for book_obj in books_obj_list %}
                                                        <tr role="row" class="odd">
                                                            <td class="sorting_1"
                                                                style="width: 50px">{{ book_obj.book_num }}</td>
                                                            <td>{{ book_obj.book_name }}</td>
                                                            <!-- 使用弹框来显示图书的详情-->
                                                            <td>
                                                                <a href="{% static book_obj.image_set.first.img_address.name %}"
                                                                   data-fancybox="group2"
                                                                   data-caption="{{ book_obj.book_name }}">
                                                                    <img src="{% static book_obj.image_set.first.img_address.name %}"
                                                                         alt="lightbox"
                                                                         class="lightbox-thumb img-thumbnail">
                                                                </a>
​
​
                                                            </td>
                                                            <td>{{ book_obj.book_type }}</td>
                                                            <td>{{ book_obj.author }}</td>
                                                            <td>{{ book_obj.book_price }}</td>
                                                            <td>{{ book_obj.book_score }}</td>
                                                            <td style="width: 100px">
                                                                <div style="width:100px;overflow: hidden;text-overflow: ellipsis">{{ book_obj.book_description }}</div>
                                                            </td>
                                                            <td>{{ book_obj.book_sales }}</td>
                                                            <td>{{ book_obj.comment_nums }}</td>
                                                            <td>{{ book_obj.book_inventory }}</td>
                                                            <td>{{ book_obj.publisher.name }}</td></tr>
                                                    {% endfor %}
​
​
                                                    </tbody></table>
                                            </div>
                                        </div>
​
​
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div><!-- End Row--></div>
    {% elif publishers_search_result == True %}
        <div class="content-wrapper">
            <div class="container-fluid"><div class="row">
                    <div class="col-lg-12">
                        <div class="card gradient-forest">
                            <div class="card gradient-forest"><h4 style="color:red">出版社查询结果</h4></div>
                            <div class="card-body text-center p-5">
                                <div class="table-responsive">
                                    <div id="default-datatable_wrapper"
                                         class="dataTables_wrapper container-fluid dt-bootstrap4"></div>
                                    <div class="row">
                                        <div class="col-sm-12">
                                            <table class="table table-dark table-striped shadow-dark">
                                                <thead>
                                                <tr role="row" class="odd">
                                                    <th class="sorting_asc" tabindex="0"
                                                        aria-controls="default-datatable" rowspan="1" colspan="1"
                                                        aria-sort="ascending"
                                                        aria-label="Name: activate to sort column descending"
                                                        style="width: 140px;
                                                    font-size:17px">
                                                        <p>出版社id</p>
                                                    </th>
                                                    <th class="sorting" tabindex="0" aria-controls="default-datatable"
                                                        rowspan="1" colspan="1"
                                                        aria-label="Name: activate to sort column descending"
                                                        style="width: 225px;font-size:17px"><p>出版社</p>
                                                    </th>
                                                    <th class="sorting" tabindex="0" aria-controls="default-datatable"
                                                        rowspan="1" colspan="1"
                                                        aria-label="Name: activate to sort column descending"
                                                        style="width: 101px;font-size:17px"><p>出版社地址</p>
                                                    </th>
                                                </tr>
                                                </thead>
                                                <tbody>
                                                {% for publisher_obj in publishers_obj_list %}
                                                    <tr role="row" class="odd">
                                                        <td class="sorting_1">{{ publisher_obj.id }}</td>
                                                        <td>{{ publisher_obj.name }}</td>
                                                        <td>{{ publisher_obj.address }}</td>
                                                    </tr>
                                                {% endfor %}
​
​
                                                </tbody></table>
                                        </div>
                                    </div></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    {% else %}
        <div id="wrapper"><div class="container" style="margin: 20px 310px">
                <div class="row">
                    <div class="col-md-12">
                        <div class="text-center error-pages">
                            <h1 class="error-title text-white"> 404</h1>
                            <h2 class="error-sub-title text-white">查询失败</h2><p class="error-message text-white text-uppercase">{{ error_msg }}</p><div class="mt-4">
                                <a href="/librarian/index/" class="btn btn-info btn-round shadow-info m-1">返回主页</a>
                                {#                          <a href="javascript:void();" class="btn btn-info btn-round m-1">Previous Page </a>#}
                            </div>
​
​
                            <hr class="w-50 border-light-2">
                            <hr class="w-50 border-light-2">
                        </div>
                    </div>
                </div>
            </div></div><!--wrapper-->
    {% endif %}

查询图书结果页面,如下图所示

image-20210718163019803

查询出版社结果页面,如下图所示

image-20210718163035579

如果查询失败的页面效果,如下图所示。

image-20210718163056072

二、解决侧边栏的问题

要实现如下图所示的侧边栏的功能其实也很简单,就是ul 标签下的li标签中嵌套ul...li标签和a标签来实现的。

640.gif

实现上图效果代码如下:

<ul class="sidebar-menu do-nicescrol">
            <li class="sidebar-header">主导航</li>
            <li>
                <a href="index.html" class="waves-effect">
                    <i class="zmdi zmdi-view-dashboard"></i> <span>出版社管理页面</span> <i
                        class="fa fa-angle-left pull-right"></i>
                </a>
                <ul class="sidebar-submenu">
                    <li><a href="/librarian/add_publisher"><i class="zmdi zmdi-star-outline"></i>添加出版社</a></li>
                    <li><a href="/librarian/publisher_list/"><i class="zmdi zmdi-star-outline"></i>出版社列表</a></li>
                </ul>
            </li>
            <li>
                <a href="javaScript:void();" class="waves-effect">
                    <i class="zmdi zmdi-layers"></i>
                    <span>图书管理页面</span> <i class="fa fa-angle-left pull-right"></i>
                </a>
                <ul class="sidebar-submenu">
                    <li><a href="/librarian/add_book"><i class="zmdi zmdi-star-outline"></i> 添加图书</a></li>
                    <li><a href="/librarian/book_list"><i class="zmdi zmdi-star-outline"></i> 图书列表</a></li>
                </ul>
            </li>
            <li>
                <a href="javaScript:void();" class="waves-effect">
                    <i class="zmdi zmdi-gamepad"></i> <span>作者管理页面</span>
                    <i class="fa fa-angle-left float-right"></i>
                </a>
                <ul class="sidebar-submenu">
                    <li><a href="/librarian/add_author"><i class="zmdi zmdi-star-outline"></i> 添加作者</a></li>
                    <li><a href="/librarian/author_list"><i class="zmdi zmdi-star-outline"></i> 作者列表</a></li>
                </ul>
            </li>
            <li>
                <a href="javaScript:void();" class="waves-effect">
                    <i class="zmdi zmdi-gamepad"></i> <span>用户管理页面</span>
                    <i class="fa fa-angle-left float-right"></i>
                </a>
                <ul class="sidebar-submenu">
                    <li><a href="/librarian/add_user"><i class="zmdi zmdi-star-outline"></i> 添加用户</a></li>
                    <li><a href="/librarian/user_list"><i class="zmdi zmdi-star-outline"></i> 用户列表</a></li>
                </ul>
            </li><li class="sidebar-header">更多</li>
            <li><a href="javaScript:void();" class="waves-effect"><i class="zmdi zmdi-share text-info"></i> <span>Information</span></a>
            </li>
        </ul>

我是梓栋,我们下期见!