怎么在Django中利用haystack和whoosh实现一个搜索功能
这期内容当中小编将会给大家带来有关怎么在Django中利用haystack和whoosh实现一个搜索功能,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。
安装和配置
安装所需包
pipinstalldjango-haystack pipinstallwhoosh pipinstalljieba
去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 文件,截图如下:
在 search_indexes.py 文件中加入以下内容
#定义索引类 fromhaystackimportindexes #导入你的模型类 fromgoods.modelsimportGoodsSKU #指定对于某个类的某些数据建立索引 #索引类名格式:模型类名+Index classGoodsSKUIndex(indexes.SearchIndex,indexes.Indexable): #索引字段use_template=True指定根据表中的哪些字段建立索引文件的说明放在一个文件中 text=indexes.CharField(document=True,use_template=True) defget_model(self): #返回你的模型类 returnGoodsSKU #建立索引的数据 defindex_queryset(self,using=None): returnself.get_model().objects.all()
指定要检索的内容
在templates文件夹下面新建search文件夹,在search文件夹下面新建indexes文件夹,在indexes文件夹下面新建要检索应用名的文件夹比如goods文件夹,在goods文件夹下面新建 表名_text.txt,表名小写,所以目前的目录结构是这样的 templates/search/indexes/goods/goodssku_text.txt ,截图如下:
在goodssku_text.txt 文件中指定你要根据表中的哪些字段建立索引数据,现在我们要根据商品的名称,简介,详情来建立索引,如下配置
#指定根据表中的哪些字段建立索引数据 {{object.name}}#根据商品的名称建立索引 {{object.desc}}#根据商品的简介建立索引 {{object.goods.detail}}#根据商品的详情建立索引
其中的objects可以理解为数据表对应的商品对象。
生成索引文件
使用pycharm自带的命令行terminal运行以下命令生成索引文件:
python manage.py rebuild_index
运行成功后,你可以在项目下看到类似如下索引文件
使用全文检索
通过如上的配置,我们的数据索引已经建立了,现在我们要在项目中使用全文检索。
在需要使用检索的地方进行 form 表单改造
<formaction="/search"method="get"> <inputtype="text"class="input_textfl"name="q"placeholder="搜索商品"> <inputtype="submit"class="input_btnfr"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对象。
可以通过如下代码测试参数
<!DOCTYPEhtml> <htmllang="en"> <head> <metacharset="UTF-8"> <title>Title</title> </head> <body>
搜索的关键字:{{query}}<br/> 当前页的Page对象:{{page}}<br/> <ul> {%foriteminpage%} <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,注意路径和文件名是固定的,如下图
利用检索返回的参数在search.html中定义要渲染出的模板和样式,我的页面如下
<divclass="breadcrumb"> <ahref="#">{{query}}</a> <span>></span> <ahref="#">搜索结果如下:</a> </div> <divclass="main_wrapclearfix"> <ulclass="goods_type_listclearfix"> {%foriteminpage%} <li> <ahref="{%url'goods:detail'item.object.id%}"><imgsrc="{{item.object.image.url}}"></a> <h5><ahref="{%url'goods:detail'item.object.id%}">{{item.object.name}}</a></h5> <divclass="operate"> <spanclass="prize">¥{{item.object.price}}</span> <spanclass="unit">{{item.object.price}}/{{item.object.unite}}</span> <ahref="#"class="add_goods"title="加入购物车"></a> </div> </li> {%endfor%} </ul> <divclass="pagenation"> {%ifpage.has_previous%} <ahref="/search?q={{query}}&page={{page.previous_page_number}}"><上一页</a> {%endif%} {%forpindexinpaginator.page_range%} {%ifpindex==page.number%} <ahref="/search?q={{query}}&page={{pindex}}"class="active">{{pindex}}</a> {%else%} <ahref="/search?q={{query}}&page={{pindex}}">{{pindex}}</a> {%endif%} {%endfor%} {%ifpage.has_next%} <ahref="/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 文件
目录如下图
在文件中添加如下内容
importjieba fromwhoosh.analysisimportTokenizer,Token classChineseTokenizer(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) forwinseglist: t.original=t.text=w t.boost=1.0 ifpositions: t.pos=start_pos+value.find(w) ifchars: t.startchar=start_char+value.find(w) t.endchar=start_char+value.find(w)+len(w) yieldt defChineseAnalyzer(): returnChineseTokenizer()
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'
重新生成索引文件
pythonmanage.pyrebuild_index
至此,就可以放心的使用搜索功能了,如图,搜索成功的显示页面
可以通过如下配置控制每个分页显示的搜索出来对象的数目
#指定搜索结果每页显示的条数 HAYSTACK_SEARCH_RESULTS_PER_PAGE=1
上述就是小编为大家分享的怎么在Django中利用haystack和whoosh实现一个搜索功能了,如果刚好有类似的疑惑,不妨参照上述分析进行理解。如果想知道更多相关知识,欢迎关注恰卡编程网行业资讯频道。
推荐阅读
-
浅析Django接口版本控制
-
Django+Celery实现定时任务的示例
-
Python(django中如何使用restful框架)
-
Django实现drf搜索过滤和排序过滤
-
Django中怎么将ValuesQuerySet转换成json
今天就跟大家聊聊有关Django中怎么将ValuesQuerySet转换成json,可能很多人都不太了解,为了让大家更加了解,小编...
-
Django分页器的使用方法
这篇文章主要介绍了Django分页器的使用方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面...
-
Python Django搭建文件下载服务器的实现shili
-
在Django中如何使用MQTT的方法
这篇文章主要介绍了在Django中如何使用MQTT的方法,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有...
-
Django开发RESTful API怎么实现增删改查
-
Django如何显示可视化图表的实践