Django 博客实现简单的全文搜索的示例代码


Posted in Python onFebruary 17, 2020

作者:HelloGitHub-追梦人物

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

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

概述

博客文章通常包含标题和正文两个部分。当用户输入某个关键词进行搜索后,我们希望为用户显示标题和正文中含有被搜索关键词的全部文章。整个搜索的过程如下:

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

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

将关键词提交给服务器

先来回顾一下我们的 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 表单代码大概像这样:

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 里:

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 搜索引擎的使用方法。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python基础教程之元组操作使用详解
Mar 25 Python
python中List的sort方法指南
Sep 01 Python
举例讲解Python中的死锁、可重入锁和互斥锁
Nov 05 Python
windows下安装python的C扩展编译环境(解决Unable to find vcvarsall.bat)
Feb 21 Python
python pandas 对时间序列文件处理的实例
Jun 22 Python
python十进制和二进制的转换方法(含浮点数)
Jul 07 Python
python读取Excel实例详解
Aug 17 Python
Python实战之制作天气查询软件
May 14 Python
深入解析神经网络从原理到实现
Jul 26 Python
深入浅析python 中的self和cls的区别
Jun 20 Python
Python下使用Trackbar实现绘图板
Oct 27 Python
Python Pycharm虚拟下百度飞浆PaddleX安装报错问题及处理方法(亲测100%有效)
May 24 Python
Python使用qrcode二维码库生成二维码方法详解
Feb 17 #Python
django2.2 和 PyMySQL版本兼容问题
Feb 17 #Python
基于python3的socket聊天编程
Feb 17 #Python
python词云库wordCloud使用方法详解(解决中文乱码)
Feb 17 #Python
python词云库wordcloud的使用方法与实例详解
Feb 17 #Python
tensorflow保持每次训练结果一致的简单实现
Feb 17 #Python
Python基于Socket实现简单聊天室
Feb 17 #Python
You might like
php数组查找函数in_array()、array_search()、array_key_exists()使用实例
2014/04/29 PHP
PHP中mysql_field_type()函数用法
2014/11/24 PHP
PHP list() 将数组中的值赋给变量的简单实例
2016/06/13 PHP
老生常谈PHP中的数据结构:DS扩展
2017/07/17 PHP
PHP html_entity_decode()函数讲解
2019/02/25 PHP
用JavaScrpt实现文件夹简单轻松加密的实现方法图文
2008/09/08 Javascript
JavaScript中的Array对象使用说明
2011/01/17 Javascript
jquery显示隐藏input对象
2014/07/21 Javascript
处理文本部分内容的TextRange对象应用实例
2014/07/29 Javascript
javascript文件加载管理简单实现方法
2015/07/25 Javascript
JavaScript中的splice方法用法详解
2016/07/20 Javascript
详解微信小程序开发—你期待的分享功能来了,微信小程序序新增5大功能
2016/12/23 Javascript
Easyui ueditor 整合解决不能编辑的问题(推荐)
2017/06/25 Javascript
浅谈原生JS中的延迟脚本和异步脚本
2017/07/12 Javascript
JavaScript实现简单计算器
2020/03/19 Javascript
vue使用svg文件补充-svg放大缩小操作(使用d3.js)
2020/09/22 Javascript
基于elementUI竖向表格、和并列的案例
2020/10/26 Javascript
[01:03:36]Ti4 循环赛第三日DK vs Titan
2014/07/12 DOTA
python基础教程之自定义函数介绍
2014/08/29 Python
python获取list下标及其值的简单方法
2016/09/12 Python
django使用html模板减少代码代码解析
2017/12/12 Python
使用python装饰器计算函数运行时间的实例
2018/04/21 Python
解决PyCharm同目录下导入模块会报错的问题
2018/10/13 Python
python中使用.py配置文件的方法详解
2020/11/23 Python
python通过cython加密代码
2020/12/11 Python
python脚本使用阿里云slb对恶意攻击进行封堵的实现
2021/02/04 Python
css 省略号 css3让多余的字符串消失并附加省略号的实现代码
2013/02/07 HTML / CSS
阿玛瑞酒店中文官方网站:Amari.com
2018/02/13 全球购物
欧姆龙医疗欧洲有限公司:Omron Healthcare Europe B.V
2020/06/13 全球购物
以下为Windows NT 下的32 位C++程序,请计算sizeof 的值
2016/12/07 面试题
卫生安全检查制度
2014/02/04 职场文书
《我的第一本书》教学反思
2014/02/15 职场文书
2016婚礼主持词开场白
2015/11/24 职场文书
求职自我评价参考范文
2019/05/16 职场文书
Python数组变形的几种实现方法
2022/05/30 Python
Redis过期数据是否会被立马删除
2022/07/23 Redis