部署:
在settings.py文件中注册haystack, 并做如下配置:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.sites', # Added. 'haystack', # Then your usual apps... 'blog', ]import os
在应用目录下创建一个search_indexes.py
import datetime from haystack import indexes from myapp.models import Note class NoteIndex(indexes.SearchIndex, indexes.Indexable): text = indexes.CharField(document=True, use_template=True) author = indexes.CharField(model_attr='user') pub_date = indexes.DateTimeField(model_attr='pub_date') def get_model(self): return Note def index_queryset(self, using=None): """Used when the entire index for model is updated.""" return self.get_model().objects.filter(pub_date__lte=datetime.datetime.now())
use_template=True 说明您一会会在一个文件中指定要建立索引的字段,这个一会我们会说。建立索引,是说要搜索哪些字段,没有建立索引的字段不在搜索的范围之内。
需要注意的是,类名是由学问的,它的组成是要建立索引的模型类+Index,比如,我要搜索的模型类是GoodsSKU,那么我的类名就是GoodsSKU,也就是:
class GoodsSKUIndex(indexes.SearchIndex, indexes.Indexable): 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/indexes/myapp/GoodsSKU_text.txt, 这里面要指定的,就是刚刚说的要建立索引的字段。
{{ object.name }}# 根据商品的名称建立索引
{{ object.desc }}# 根据商品的简介建立索引
{{ object.goods.detail }} # 根据商品详情信息建立索引
./manage.py rebuild_index 这个命令会生成索引
配置URL:
url(r'^search/', include('haystack.urls')),基本的部署已经结束了,接下来就是使用了。
一般,我们会在首页建一个form,来调用搜索引擎。
<form method="get" action="."> <table> {{ form.as_table }} <tr> <td> td> <td> <input type="submit" value="Search"> td> tr> table> {% if query %} <h3>Resultsh3> {% for result in page.object_list %} <p> <a href="{{ result.object.get_absolute_url }}">{{ result.object.title }}a> p> {% empty %} <p>No results found.p> {% endfor %} {% if page.has_previous or page.has_next %} <div> {% if page.has_previous %}<a href="?q={{ query }}&page={{ page.previous_page_number }}">{% endif %}« Previous{% if page.has_previous %}a>{% endif %} | {% if page.has_next %}<a href="?q={{ query }}&page={{ page.next_page_number }}">{% endif %}Next »{% if page.has_next %}a>{% endif %} div> {% endif %} {% else %} {# Show some example queries to run, maybe query syntax, something else? #} {% endif %} form>
上面的是官方示例,这个示例少个输入框。我补充下:
大家要注意,name = 'q'是不能更改的,只能这么写。
搜索结果出来后,搜索引擎会把结果返给emplates/search目录下的search.html
具体返回的内容包括:
query 搜索关键词
page 当前页的page对象(引擎默认已经给搜索结果分页了)
paginator 分页对象
这里需要特别指出的是,遍历page后,需要在后面加上.object,这样得到的才是模型类对象。
HAYSTACK_SEARCH_RESULTS_PER_PAGE 可以用来指定每页显示的条目数,写在settings里。
到此为止,搜索引擎就已经可以正常使用了。但是,在使用的过程中,我们可能会对引擎的分词能力不满意。那么,我们可以安装jieba。它的一个优势就是——免费!
pip install jieba
找到虚拟环境py_django下的haystack目录。
/home/python/.virtualenvs/bj17_py3/lib/python3.5/site-packages/haystack/backends/
在上面的目录中创建ChineseAnalyzer.py文件。
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()
复制whoosh_backend.py文件,改为如下名称。
whoosh_cn_backend.py
打开复制出来的新文件,引入中文分析类,内部采用jieba分词。
from .ChineseAnalyzer import ChineseAnalyzer
更改词语分析类。
查找
analyzer=StemmingAnalyzer()
改为
analyzer=ChineseAnalyzer()
修改settings.py文件中的配置项。把其中的,whoosh_backend改为whoosh_cn_backend
然后重启搜索引擎,大功告成!python manage.py rebuild_index
<form method="get" action="."> <table> {{ form.as_table }} <tr> <td> td> <td> <input type="submit" value="Search"> td> tr> table> {% if query %} <h3>Resultsh3> {% for result in page.object_list %} <p> <a href="{{ result.object.get_absolute_url }}">{{ result.object.title }}a> p> {% empty %} <p>No results found.p> {% endfor %} {% if page.has_previous or page.has_next %} <div> {% if page.has_previous %}<a href="?q={{ query }}&page={{ page.previous_page_number }}">{% endif %}« Previous{% if page.has_previous %}a>{% endif %} | {% if page.has_next %}<a href="?q={{ query }}&page={{ page.next_page_number }}">{% endif %}Next »{% if page.has_next %}a>{% endif %} div> {% endif %} {% else %} {# Show some example queries to run, maybe query syntax, something else? #} {% endif %} form>