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 19 Python
django将图片上传数据库后在前端显式的方法
May 25 Python
便捷提取python导入包的属性方法
Oct 15 Python
从运行效率与开发效率比较Python和C++
Dec 14 Python
pyttsx3实现中文文字转语音的方法
Dec 24 Python
Python面向对象程序设计类的多态用法详解
Apr 12 Python
用uWSGI和Nginx部署Flask项目的方法示例
May 05 Python
Windows 安装 Anaconda3+PyCharm的方法步骤
Jun 13 Python
将python运行结果保存至本地文件中的示例讲解
Jul 11 Python
python如何删除文件中重复的字段
Jul 16 Python
python基础 range的用法解析
Aug 23 Python
pandas使用之宽表变窄表的实现
Apr 12 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技巧与注意事项分析
2011/02/03 PHP
探讨Smarty中如何获取数组的长度以及smarty调用php函数的详解
2013/06/20 PHP
php模拟ping命令(php exec函数的使用方法)
2013/10/25 PHP
php判断当前用户已在别处登录的方法
2015/01/06 PHP
Smarty模板引擎缓存机制详解
2016/05/23 PHP
PHP实现一个多功能购物网站的案例
2017/09/13 PHP
jQuery操作input type=radio的实现代码
2012/06/14 Javascript
JS往数组中添加项性能分析
2015/02/25 Javascript
第二次聊一聊JS require.js模块化工具的基础知识
2016/04/17 Javascript
详解Node.js模块间共享数据库连接的方法
2016/05/24 Javascript
深入分析node.js的异步API和其局限性
2016/09/05 Javascript
jQuery  ready方法实现原理详解
2016/10/19 Javascript
用jmSlip编写移动端顶部日历选择控件
2016/10/24 Javascript
webpack中CommonsChunkPlugin详细教程(小结)
2017/11/09 Javascript
mongoose更新对象的两种方法示例比较
2017/12/19 Javascript
JavaScript面向对象继承原理与实现方法分析
2018/08/09 Javascript
Vue项目数据动态过滤实践及实现思路
2018/09/11 Javascript
代码实例ajax实现点击加载更多数据图片
2018/10/12 Javascript
Node.JS用纯JavaScript生成图片或滑块式验证码功能
2019/09/12 Javascript
改变layer confirm弹窗按钮的颜色方法
2019/09/12 Javascript
使用 UniApp 实现小程序的微信登录功能
2020/06/09 Javascript
vue 通过绑定事件获取当前行的id操作
2020/07/27 Javascript
[01:00]一分钟回顾2018DOTA2亚洲邀请赛现场活动
2018/04/07 DOTA
[42:52]Optic vs Serenity 2018国际邀请赛淘汰赛BO3 第二场 8.22
2018/08/23 DOTA
python在多玩图片上下载妹子图的实现代码
2013/08/13 Python
Python深入学习之对象的属性
2014/08/31 Python
Python中asyncore异步模块的用法及实现httpclient的实例
2016/06/28 Python
Python3.5内置模块之os模块、sys模块、shutil模块用法实例分析
2019/04/27 Python
Python使用import导入本地脚本及导入模块的技巧总结
2019/08/07 Python
python2 对excel表格操作完整示例
2020/02/23 Python
Linux内核产生并发的原因
2016/11/08 面试题
房屋买卖协议书范本
2014/04/10 职场文书
2014年医药代表工作总结
2014/11/22 职场文书
社团个人总结范文
2015/03/05 职场文书
婚礼伴郎致辞
2015/07/28 职场文书
超详细Python解释器新手安装教程
2021/05/10 Python