Django中使用haystack+whoosh实现搜索功能


Posted in Python onOctober 08, 2019

为了实现项目中的搜索功能,我们使用的是全文检索框架haystack+搜索引擎whoosh+中文分词包jieba

安装和配置

安装所需包

pip install django-haystack
pip install whoosh
pip install jieba

去settings文件注册haystack应用

INSTALLED_APPS = [
 'haystack', # 注册全文检索框架
]

在settings文件中配置全文检索框架

# 全文检索框架的配置
HAYSTACK_CONNECTIONS = {
 'default': {
  # 使用whoosh引擎
  'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
  # 索引文件路径
  'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
 }
}

# 当添加、修改、删除数据时,自动生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

索引文件的生成

要生成索引文件,首先你要配置,对哪些内容进行索引,比如商品名称,简介和详情;为了配置对数据库指定内容进行索引,我们要做如下步骤:

配置search_indexes.py文件

因为在django中数据库一般都是通过ORM生成的,首先我们在要在数据表对应的应用中创建一个 search_indexes.py 文件,例如,我现在要检索商品对应的表就是GoodsSKU表,而表是在goods应用下的,所以我在goods应用下新建 search_indexes.py 文件,截图如下:

Django中使用haystack+whoosh实现搜索功能

在 search_indexes.py 文件中加入以下内容

# 定义索引类
from haystack import indexes
# 导入你的模型类
from goods.models import GoodsSKU
# 指定对于某个类的某些数据建立索引
# 索引类名格式:模型类名+Index
class GoodsSKUIndex(indexes.SearchIndex, indexes.Indexable):
 # 索引字段 use_template=True指定根据表中的哪些字段建立索引文件的说明放在一个文件中
 text = indexes.CharField(document=True, use_template=True)
 def get_model(self):
  # 返回你的模型类
  return GoodsSKU
 # 建立索引的数据
 def index_queryset(self, using=None):
  return self.get_model().objects.all()

指定要检索的内容

在templates文件夹下面新建search文件夹,在search文件夹下面新建indexes文件夹,在indexes文件夹下面新建要检索应用名的文件夹比如goods文件夹,在goods文件夹下面新建 表名_text.txt,表名小写,所以目前的目录结构是这样的 templates/search/indexes/goods/goodssku_text.txt ,截图如下:

Django中使用haystack+whoosh实现搜索功能

在goodssku_text.txt 文件中指定你要根据表中的哪些字段建立索引数据,现在我们要根据商品的名称,简介,详情来建立索引,如下配置

# 指定根据表中的哪些字段建立索引数据
{{ object.name }} # 根据商品的名称建立索引
{{ object.desc }} # 根据商品的简介建立索引
{{ object.goods.detail }} # 根据商品的详情建立索引

其中的objects可以理解为数据表对应的商品对象。

生成索引文件

使用pycharm自带的命令行terminal运行以下命令生成索引文件:

python manage.py rebuild_index

运行成功后,你可以在项目下看到类似如下索引文件

Django中使用haystack+whoosh实现搜索功能

使用全文检索

通过如上的配置,我们的数据索引已经建立了,现在我们要在项目中使用全文检索。

在需要使用检索的地方进行 form 表单改造

<form action="/search" method="get">
 <input type="text" class="input_text fl" name="q" placeholder="搜索商品">
 <input type="submit" class="input_btn fr" name="" value="搜索">
</form>

如上所示,其中要注意的是:

发送方式必须使用get;

搜索的input框 name 必须是 q;

配置检索对应的url

在项目下的urls.py文件中添加如下url配置

urlpatterns = [
 url(r'^search/', include('haystack.urls')), # 全文检索框架
]

检索成功后生成的参数

当haystack自动检索成功后,会给我们返回三个参数;

query参数,表示你查询的参数;

page参数,当前页的Page对象,是查询到的对象的集合,可以通过for循环类获取单个商品,通过 商品.objects.xxx 获取商品对应的字段;

paginator参数,分页paginator对象。

可以通过如下代码测试参数

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <title>Title</title>
</head>
<body>
搜索的关键字:{{ query }}<br/>
当前页的Page对象:{{ page }}<br/>
<ul>
 {% for item in page %}
  <li>{{ item.object }}</li>
 {% endfor %}
</ul>
分页paginator对象:{{ paginator }}<br/>
</body>
</html>

templates/indexes/search.html

注意,位置和文件名都是固定的,并且这只是测试文件,后面使用全文检索时记得不能使用search.html,改成其他名字。

数据+search.html返回渲染后页面

当haystack全文检索后会返回数据,现在我们需要一个页面来接收这些数据,并且在页面渲染后返回这个页面给用户观看,渲染并返回页面的工作haystack已经帮我们做了,那么我们现在只需要准备一个页面容纳数据即可。

在templates文件夹下的indexes文件夹下新建一个search.html,注意路径和文件名是固定的,如下图

Django中使用haystack+whoosh实现搜索功能

利用检索返回的参数在search.html中定义要渲染出的模板和样式,我的页面如下

<div class="breadcrumb">
 <a href="#">{{ query }}</a>
 <span>></span>
 <a href="#">搜索结果如下:</a>
</div>
<div class="main_wrap clearfix">
 <ul class="goods_type_list clearfix">
  {% for item in page %}
  <li>
   <a href="{% url 'goods:detail' item.object.id %}"><img src="{{ item.object.image.url }}"></a>
   <h4><a href="{% url 'goods:detail' item.object.id %}">{{ item.object.name }}</a></h4>
   <div class="operate">
    <span class="prize">¥{{ item.object.price }}</span>
    <span class="unit">{{ item.object.price}}/{{ item.object.unite }}</span>
    <a href="#" class="add_goods" title="加入购物车"></a>
   </div>
  </li>
  {% endfor %}
 </ul>
 <div class="pagenation">
   {% if page.has_previous %}
   <a href="/search?q={{ query }}&page={{ page.previous_page_number }}"><上一页</a>
   {% endif %}
   {% for pindex in paginator.page_range %}
    {% if pindex == page.number %}
     <a href="/search?q={{ query }}&page={{ pindex }}" class="active">{{ pindex }}</a>
    {% else %}
     <a href="/search?q={{ query }}&page={{ pindex }}">{{ pindex }}</a>
    {% endif %}
   {% endfor %}
   {% if page.has_next %}
   <a href="/search?q={{ query }}&page={{ page.next_page_number }}">下一页></a>
   {% endif %}
  </div>
</div>

search.html

至此,我们可以在页面上搜索一下内容,应该是能成功的,但也有可能不会返回任何数据就算name就是你搜索的内容,这是因为我们现在使用的主要还是为英语服务的分词包,接下来我们要配置使用中文分词包了。

使用中文分词包jieba

在前面的配置中我们已经安装了jieba;

创建 ChineseAnalyzer.py 文件

进入虚拟环境下的 Lib\site-packages\haystack\backends 目录下新建 ChineseAnalyzer.py 文件

目录如下图

Django中使用haystack+whoosh实现搜索功能

在文件中添加如下内容

import jieba
from whoosh.analysis import Tokenizer, Token
class ChineseTokenizer(Tokenizer):
 def __call__(self, value, positions=False, chars=False,
     keeporiginal=False, removestops=True,
     start_pos=0, start_char=0, mode='', **kwargs):
  t = Token(positions, chars, removestops=removestops, mode=mode,
     **kwargs)
  seglist = jieba.cut(value, cut_all=True)
  for w in seglist:
   t.original = t.text = w
   t.boost = 1.0
   if positions:
    t.pos = start_pos + value.find(w)
   if chars:
    t.startchar = start_char + value.find(w)
    t.endchar = start_char + value.find(w) + len(w)
   yield t
def ChineseAnalyzer():
 return ChineseTokenizer()

ChineseAnalyzer.py

编写haystack可使用的 whoosh_cn_backend.py 文件

直接在 虚拟环境下的 Lib\site-packages\haystack\backends 目录下复制一份 whoosh_backend.py 文件 并且重命名复制文件为 whoosh_cn_backend.py;

在 whoosh_cn_backend.py 中导入我们编写的 ChineseAnalyzer 类

from .ChineseAnalyzer import ChineseAnalyzer

更改haystack使用的分词包为 jieba 编写的中文分词类,大概在第160行左右

# schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=StemmingAnalyzer(), field_boost=field_class.boost, sortable=True)
schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=ChineseAnalyzer(), field_boost=field_class.boost, sortable=True)

配置whoosh引擎使用 whoosh_cn_backend.py

在settings文件中更改原来的配置如下

# 全文检索框架的配置
HAYSTACK_CONNECTIONS = {
 'default': {
  # 使用whoosh引擎
  # 'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
  'ENGINE': 'haystack.backends.whoosh_cn_backend.WhooshEngine',
  # 索引文件路径
  'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
 }
}
# 当添加、修改、删除数据时,自动生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

重新生成索引文件

python manage.py rebuild_index

至此,就可以放心的使用搜索功能了,如图,搜索成功的显示页面

Django中使用haystack+whoosh实现搜索功能

可以通过如下配置控制每个分页显示的搜索出来对象的数目

# 指定搜索结果每页显示的条数
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 1

总结

以上所述是小编给大家介绍的Django之使用haystack+whoosh实现搜索功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
以windows service方式运行Python程序的方法
Jun 03 Python
python 循环遍历字典元素的简单方法
Sep 11 Python
Python简单基础小程序的实例代码
Apr 28 Python
Python csv文件的读写操作实例详解
Nov 19 Python
pytorch中tensor.expand()和tensor.expand_as()函数详解
Dec 27 Python
python误差棒图errorbar()函数实例解析
Feb 11 Python
python GUI库图形界面开发之PyQt5时间控件QTimer详细使用方法与实例
Feb 26 Python
python利用Excel读取和存储测试数据完成接口自动化教程
Apr 30 Python
利用OpenCV中对图像数据进行64F和8U转换的方式
Jun 03 Python
python爬虫多次请求超时的几种重试方法(6种)
Dec 01 Python
深入理解Python变量的数据类型和存储
Feb 01 Python
golang特有程序结构入门教程
Jun 02 Python
python 使用while写猜年龄小游戏过程解析
Oct 07 #Python
python getpass模块用法及实例详解
Oct 07 #Python
Python拆分大型CSV文件代码实例
Oct 07 #Python
Python模块汇总(常用第三方库)
Oct 07 #Python
python numpy之np.random的随机数函数使用介绍
Oct 06 #Python
python系列 文件操作的代码
Oct 06 #Python
pip 安装库比较慢的解决方法(国内镜像)
Oct 06 #Python
You might like
PHP入门
2006/10/09 PHP
修改了一个很不错的php验证码(支持中文)
2007/02/14 PHP
PHP中文URL编解码(urlencode()rawurlencode()
2010/07/03 PHP
php中时间轴开发(刚刚、5分钟前、昨天10:23等)
2011/10/03 PHP
ThinkPHP3.1新特性之内容解析输出详解
2014/06/19 PHP
PHP curl使用实例
2015/07/02 PHP
PHP使用http_build_query()构造URL字符串的方法
2016/04/02 PHP
IE和Firefox的Javascript兼容性总结[推荐收藏]
2011/10/19 Javascript
node.js中的fs.readdirSync方法使用说明
2014/12/17 Javascript
整理Javascript基础入门学习笔记
2015/11/29 Javascript
JS多物体实现缓冲运动效果示例
2016/12/20 Javascript
JS实现的验证身份证及获取地区功能示例
2017/01/16 Javascript
JS 实现 ajax 异步浏览器兼容问题
2017/01/21 Javascript
vue实现自定义日期组件功能的实例代码
2018/11/06 Javascript
js实现延迟加载的几种方法详解
2019/01/19 Javascript
详解Vue项目中实现锚点定位
2019/04/24 Javascript
vue跳转页面的几种方法(推荐)
2020/03/26 Javascript
Python中实现远程调用(RPC、RMI)简单例子
2014/04/28 Python
python 文件操作删除某行的实例
2017/09/04 Python
python学习基础之循环import及import过程
2018/04/22 Python
Kali Linux安装ipython2 和 ipython3的方法
2019/07/11 Python
react+django清除浏览器缓存的几种方法小结
2019/07/17 Python
Python学习笔记之Break和Continue用法分析
2019/08/14 Python
使用Django xadmin 实现修改时间选择器为不可输入状态
2020/03/30 Python
python实现学生成绩测评系统
2020/06/22 Python
Python eval函数介绍及用法
2020/11/09 Python
亚马逊墨西哥站:Amazon.com.mx
2018/08/26 全球购物
八年级生物教学反思
2014/01/22 职场文书
小学防溺水制度
2014/01/29 职场文书
巾帼志愿者活动方案
2014/08/17 职场文书
公务员政审材料范文
2014/12/23 职场文书
玄武湖导游词
2015/02/05 职场文书
2015迎新晚会开场白
2015/07/17 职场文书
python学习之panda数据分析核心支持库
2021/05/07 Python
超详细Python解释器新手安装教程
2021/05/10 Python
利用Sharding-Jdbc进行分库分表的操作代码
2022/01/22 Java/Android