快速入门
环境安装
首先需要清楚以下各个库的作用
django
是基于python开发的web框架,阅读本文需要了解相关的基础知识django-haystack
为 Django 提供模块化搜索。它具有统一、熟悉的 API,允许您插入不同的搜索后端(例如Solr、 Elasticsearch、Whoosh、Xapian等),而无需修改代码- Whoosh 是一个用纯 Python 实现的快速、功能强大的全文索引和搜索库
# 安装相关库
pip install Django==1.11.12
pip install django-haystack==2.7.0
pip install Whoosh==2.7.4
以下几点需要注意
-
这里使用python版本为
python3.5.4
,如果其他版本可能存在不兼容 -
Whoosh
最后一次更新是2016年,可能存在效率不高、兼容不够的问题 -
django-haystack
和haystack
在当前版本不兼容,同时安装后运行项目会报错
django配置文件
进入你的django的配置文件
settings.py
,添加或修改以下配置
# HAYSTACK_CONNECTIONS配置搜索引擎,可设置多个引擎
# ENGINE为使用的引擎,设置使用whoosh
# PATH为索引存放路径
# BATCH_SIZE为索引每次更新数量
# STORAGE为索引存储形式,可选file或者ram
# POST_LIMIT为索引文件占用空间最大值,默认为128 * 1024 * 1024
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
'PATH': os.path.join(os.path.dirname(__file__), 'whoosh_index'),
'BATCH_SIZE': 1000,
'STORAGE': 'file',
'POST_LIMIT': 128 * 1024 * 1024,
},
}
# 搜索结果每页结果数量
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 10
# Haystack 是否将搜索结果限制为仅注册的模型,
HAYSTACK_LIMIT_TO_REGISTERED_MODELS = False
# 控制信号,默认为'haystack.signals.BaseSignalProcessor'
# 为haystack.signals.RealtimeSignalProcessor表示实时更新
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
注意,将
HAYSTACK_SIGNAL_PROCESSOR
设置为haystack.signals.RealtimeSignalProcessor
经过测试,只能保证通过django更新数据的索引实时性,如果直接在数据库修改数据需要更新索引保证索引实时性
建立模型索引
建立
seach_indexes.py
文件需要建立在需要检索的应用目录下,如果要检索多个可以建立多个文件
# models.py
from django.db import models
class Student(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=16)
# seach_indexes.py
from haystack import indexes
from .models import *
# 类的命名为被检索的模型名+`Index`
class StudentIndex(indexes.SearchIndex, indexes.Indexable):
# text为必须字段,表示保存索引数据
# document=True, use_template=True为必需配置
text = indexes.CharField(document=True, use_template=True)
# 可添加自定义字段,添加后表示字段可以被索引
name = indexes.CharField(model_attr="name")
def get_model(self):
# 重写获取模型方法,修改为你的模型
return Student
def index_queryset(self, using=None):
# 可加上你的过滤条件
return self.get_model().objects.all()
注意
text
为必须字段,表示索引存储的text
内容,但其字段类型可以为其它
例如NgramField
等等
其存储的内容为下列templates
文本的内容
创建templates
第一步,检查你的
setting.py
文件是否配置了templates
路径,如果没有配置,可以参考下列
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates'),], # 在这里添加你的templates路径
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
找到
/templates/search/indexes/
目录,如果没有自行创建创建目录,名为你的应用目录,如果存在多个
seach_indexes.py
创建多个目录在目录下创建txt文件,命名规则为模型名+
_text.txt
,存在多个模型需要分别创建多个txt文件
这是student_text.txt
的内容,在后续使用模板时使用,代表StudentIndex
的text
内容
如果没有此文件,当模型数据更新时会出错
字段为模型字段,非模型索引的字段
{{ object.name }}
初始化序列
第一次使用或者修改过序列模型后,需要重建索引
python manage.py rebuild_index
如果数据库批量更新数据,需要手动更新索引
python manage.py update_index
配置接口
如果使用haystack提供的接口,请在对应urls文件添加
urlpatterns = [
# 默认接口
url('search/', include('haystack.urls'), name='haystack'),
# 自定义接口
url('mysearch/', views.MySearchView.as_view(), name="search"),
]
注意,默认接口返回的是模版文件,如果需要修改为json等类型,需要自定义接口
请查看这里的代码
配置搜索界面
这里是展示官方提供的搜索模板,也可以直接调用接口
创建
/templates/search/search.html
文件
<form method="get" action=".">
<table>
{{ form.as_table }}
<tr>
<td> </td>
<td>
<input type="submit" value="Search">
</td>
</tr>
</table>
{% if query %}
<h3>Results</h3>
{% 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>
开始搜索
访问配置的接口,尝试搜索
参数 | 默认值 | 含义 |
---|---|---|
q | 传入搜索关键字,可加上~模糊搜索 | |
page | 1 | 分页,当前页数 |
models | 无参数 | 无参数表示查询全部,如果需要多个models,传入多个即可 |
自定义入参和传出JSON
class MySearchView(SearchView):
def get_form_kwargs(self):
kwargs = {'initial': self.get_initial()}
# 调整传入参数
data = self.request.GET.copy()
try:
data["q"] = data["search"]
del data["search"]
except:
pass
if self.request.method == 'GET':
kwargs.update({
'data': data,
})
kwargs.update({
'searchqueryset': self.get_queryset(),
'load_all': self.load_all,
})
return kwargs
def render_to_response(self, context, **response_kwargs):
try:
# 修改为传出json
data = []
object_list = context["object_list"]
for obj in object_list:
model_name = obj.model_name
d = {"value": obj.text,"id": obj.pk}
data.append(d)
page_obj = context["page_obj"]
paginator = page_obj.paginator
res = json.dumps(
{'success': True, "data": data, "page": {"count": paginator.count, "num_pages": paginator.num_pages,
"per_page": paginator.per_page, "index": page_obj.number}})
return HttpResponse(res, content_type="application/json")
except Exception as ex:
return JsonResponse({'success': False, 'error_message': ex})
遇到的坑
无法搜索其它字段
我在创建模型序列类的地方有备注,可以添加其它字段来进行检索,但我在
django-haystack
里没有找到相关办法默认只能检索字段
text
,虽然可以通过修改templates
文件来修改text
,但还是相当麻烦我尝试过直接使用whoosh来搜索,是可以指定字段搜索的,代码如下
# 这里是选择序列文件路径
ix = open_dir("whoosh_index")
sc = ix.schema
from whoosh.qparser import QueryParser
with ix.searcher() as searcher:
query = QueryParser("text", ix.schema).parse("检索内容")
results = searcher.search(query, collapse_limit=0, terms=True)
for i in results:
print(i)
上述代码第六行的
text
便是检索的字段名,在whoosh使用是没有问题的但是在
django-haystack
似乎默认只能检索text
这一点让我非常困惑,在相关文档里没有找到方法,本人能力有限,阅读源码没有找到解决办法
如果有大佬希望指出,非常感谢
NgramField字段无法修改最小最大值
在阅读
whoosh
文档的时候,我发现了以下两个类,可以将字段切割为N-gram
再进行索引
如下所示,是可以配置最小最大值的
minsize – N-gram 的最小长度。
maxsize – N-gram 的最大长度。
class whoosh.fields.NGRAM(minsize=2, maxsize=4, stored=False, field_boost=1.0, queryor=False, phrase=False, sortable=False)
class whoosh.fields.NGRAMWORDS(minsize=2, maxsize=4, stored=False, field_boost=1.0, tokenizer=None, at=None, queryor=False, sortable=False)
在
django-haystack
里找到对应的类
class NgramField(CharField):
field_type = 'ngram'
def __init__(self, **kwargs):
if kwargs.get('faceted') is True:
raise SearchFieldError("%s can not be faceted." % self.__class__.__name__)
super(NgramField, self).__init__(**kwargs)
class EdgeNgramField(NgramField):
field_type = 'edge_ngram'
两者皆为继承
SearchField
class SearchField(object):
"""The base implementation of a search field."""
field_type = None
def __init__(self, model_attr=None, use_template=False, template_name=None,
document=False, indexed=True, stored=True, faceted=False,
default=NOT_PROVIDED, null=False, index_fieldname=None,
facet_class=None, boost=1.0, weight=None):
# Track what the index thinks this field is called.
self.instance_name = None
self.model_attr = model_attr
self.use_template = use_template
self.template_name = template_name
self.document = document
self.indexed = indexed
self.stored = stored
self.faceted = faceted
self._default = default
self.null = null
self.index_fieldname = index_fieldname
self.boost = weight or boost
self.is_multivalued = False
# We supply the facet_class for making it easy to create a faceted
# field based off of this field.
self.facet_class = facet_class
if self.facet_class is None:
self.facet_class = FacetCharField
self.set_instance_name(None)
可以看到并没有最小最大值的的设置
更多
django-haystack
还有很多模块和功能,例如关键字高亮、搜索评分、Faceting(刻面|分面)、多个索引、日期或空间检索、复杂查询等等本文基于自身经验提供基础的安装配置以及心得,如果存在差错麻烦指出,谢谢
标签:False,self,whoosh,page,haystack,django,class From: https://www.cnblogs.com/trty/p/16597308.html