Django 博客实现简单的全文搜索

做者:HelloGitHub-追梦人物html

文中所涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库python

搜索是一个复杂的功能,但对于一些简单的搜索任务,咱们可使用 Django Model 层提供的一些内置方法来完成。如今咱们来为咱们的博客提供一个简单的搜索功能。ios

概述

博客文章一般包含标题和正文两个部分。当用户输入某个关键词进行搜索后,咱们但愿为用户显示标题和正文中含有被搜索关键词的所有文章。整个搜索的过程以下:git

  1. 用户在搜素框中输入搜索关键词,假设为 “django”,而后用户点击了搜索按钮提交其输入的结果到服务器。
  2. 服务器接收到用户输入的搜索关键词 “django” 后去数据库查找文章标题和正文中含有该关键词的所有文章。
  3. 服务器将查询结果返回给用户。

整个过程就是这样,下面来看看 Django 如何用实现这些过程。github

将关键词提交给服务器

先来回顾一下咱们的 Django 博客的 Post(文章)模型:数据库

blog/models.py

class Post(models.Model):
    # 标题
    title = models.CharField("标题", max_length=70)
    # 正文
    body = models.TextField("正文")
    
    # 其余属性...
    
	def __str__(self):
        return self.title
复制代码

先看到第 1 步,用户在搜索框输入搜索关键词,所以咱们要在博客上为用户提供一个搜索表单,HTML 表单代码大概像这样:django

templates/base.html

<form role="search" method="get" id="searchform" action="{% url 'blog:search' %}">
  <input type="search" name="q" placeholder="搜索" required>
  <button type="submit"><span class="ion-ios-search-strong"></span></button>
</form>
复制代码

特别注意这里 <input type="search" name="q" placeholder="搜索" required> 中的 name 属性,当用户在这个 input 中输入搜索内容并提交表单后,键入的数据会以键值对的形式提交服务器,这个键的名字就是经过 name 属性指定的。这样服务器就能够根据 name 的值来取得用户输入的内容。编程

用户输入了搜索关键词并点击了搜索按钮后,数据就被发送给了 Django 后台服务器。表单的 action 属性的值为 {% url 'blog:search' %}(虽然咱们尚未写这个视图函数),代表用户提交的结果将被发送给 blog 应用下 search 视图函数对应的 URL。服务器

查找含有搜索关键词的文章

搜索的功能将由 search 视图函数提供,代码写在 blog/views.py 里:app

blog/views.py

from django.contrib import messages

def search(request):
    q = request.GET.get('q')

    if not q:
        error_msg = "请输入搜索关键词"
        messages.add_message(request, messages.ERROR, error_msg, extra_tags='danger')
        return redirect('blog:index')

    post_list = Post.objects.filter(Q(title__icontains=q) | Q(body__icontains=q))
    return render(request, 'blog/index.html', {'post_list': post_list})
复制代码

首先咱们使用 request.GET.get('q') 获取到用户提交的搜索关键词。用户经过表单 get 方法提交的数据 Django 为咱们保存在 request.GET 里,这是一个相似于 Python 字典的对象,因此咱们使用 get 方法从字典里取出键 q 对应的值,即用户的搜索关键词。这里字典的键之因此叫 q 是由于咱们的表单中搜索框 input 的 name 属性的值是 q,若是修改了 name 属性的值,那么这个键的名称也要相应修改。

接下来咱们作了一个小小的校验,若是用户没有输入搜索关键词而提交了表单,咱们就无需执行查询,咱们给给用户发一条错误提醒消息,这里使用了 django messages 应用,这在 交流的桥梁:评论功能 中讲过。而后将用户重定向到首页。这里的 redirect 函数也在那篇教程中讲过。

若是用户输入了搜索关键词,咱们就经过 filter 方法从数据库里过滤出符合条件的全部文章。这里的过滤条件是 title__icontains=q,即 title 中包含(contains)关键字 q,前缀 i 表示不区分大小写。这里 icontains 是查询表达式(Field lookups),咱们在以前也使用过其余相似的查询表达式,其用法是在模型须要筛选的属性后面跟上两个下划线。Django 内置了不少查询表达式,建议过一遍 Django 官方留个印象,了解每一个表达式的做用,之后碰到相关的需求就能够快速定位到文档查询其用途 Field lookups

此外咱们这里从 from django.db.models 中引入了一个新的东西:Q 对象。Q 对象用于包装查询表达式,其做用是为了提供复杂的查询逻辑。例如这里 Q(title__icontains=q) | Q(body__icontains=q) 表示标题(title)含有关键词 q 或者正文(body)含有关键词 q ,或逻辑使用 | 符号。若是不用 Q 对象,就只能写成 title__icontains=q, body__icontains=q,这就变成标题(title)含有关键词 q 正文(body)含有关键词 q,就达不到咱们想要的目的。

绑定 URL

有了视图函数后记得把视图函数映射到相应了 URL,以下。

blog/urls.py

urlpatterns = [
    # 其余 url 配置
    path('search/', views.search, name='search'),
]
复制代码

大功告成,在导航栏尝试输入一些关键词,看看效果吧!

固然这样的搜索功能是很是简略的,难以知足一些复杂的搜索需求。编写一个搜索引擎是一个大工程,好在 django-haystack 这款第三方 app 为咱们完成了所有工做。使用它咱们能够实现更加复杂的搜索功能,好比全文检索、按搜索相关度排序、关键字高亮等等相似于百度搜索的功能,功能十分强大。固然其使用也会复杂一些,下一篇教程将向你们介绍 django-haystack 结合 Elasticsearch 搜索引擎的使用方法。


『讲解开源项目系列』——让对开源项目感兴趣的人再也不畏惧、让开源项目的发起者再也不孤单。跟着咱们的文章,你会发现编程的乐趣、使用和发现参与开源项目如此简单。欢迎留言联系咱们、加入咱们,让更多人爱上开源、贡献开源~

相关文章
相关标签/搜索