1. Django Haystack 简介
Django Haystack 是一个全文搜索框架,它基于 Django 的 ORM,支持搜索各种后端,包括 Elasticsearch、Solr、Whoosh 等。它易于使用,并且提供了许多有用的搜索实用程序和工具,使我们可以更容易地实现复杂的搜索。
pip install django-haystack
2. Django Haystack 安装
2.1 安装 Haystack 包
安装 Django Haystack 的包是非常简单的。只需使用 pip 包管理器,运行以下命令就可以将其安装在您的虚拟环境中:
pip install django-haystack
注意:Django Haystack 使用了 Pyramid、Whoosh、Elasticsearch、Solr、Xapian 和 Picky 这些全文搜索后端,但它们不在默认安装包中。要使用这些搜索后端,您需要手动安装适当的包,再执行以下命令:
pip install "django-haystack[elasticsearch]"
pip install "django-haystack[solr]"
pip install "django-haystack[whoosh]"
2.2 配置 Django Haystack
配置 Django Haystack 需要在 settings.py 文件中添加以下代码:
# settings.py
INSTALLED_APPS = [
# ... 其他应用
'haystack',
]
# 配置搜索后端
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.elasticsearch2_backend.Elasticsearch2SearchEngine',
'URL': 'http://localhost:9200/',
'INDEX_NAME': 'books',
},
}
上述配置说明:
INSTALLED_APPS:Haystack 必须存在于 INSTALLED_APPS 中。
ENGINE:这是搜索引擎的后端,Haystack 支持多种搜索引擎,不同的搜索引擎对应不同的后端。
URL:Elasticsearch 服务的 URL。
INDEX_NAME:Elasticsearch 中的索引名称。可以将其设置为模型名称或自定义名称。
现在 Django Haystack 配置已经完成,我们可以开始创建搜索索引了。
3. Django Haystack 创建索引
我们需要使用 Haystack 自带的管理器 SearchIndex 来为模型创建搜索索引。
SearchIndex 允许我们为每个模型指定要搜索的字段和它们的权重,以及其他搜索相关的设置。这些设置将在后面讨论。
假设有一个 Book 模型如下所示:
# models.py
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=200, null=False)
author = models.CharField(max_length=200, null=False)
publish_date = models.DateField(null=False)
isbn = models.CharField(max_length=20, null=True)
description = models.TextField(null=True)
要为 Book 模型创建索引,我们需要创建一个名为 BookIndex 的类,它继承自 SearchIndex,并定义以下内容:
text:定义将要搜索的内容。
author:定义作者字段的搜索方式。
publish_date:定义出版日期字段的搜索方式。
isbn:定义 ISBN 字段的搜索方式。
get_model():定义哪个模型与索引相关联。在此示例中,它是 Book 模型。
BookIndex 类的完整定义如下所示:
# search_indexes.py
from haystack import indexes
from .models import Book
class BookIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
author = indexes.CharField(model_attr='author')
publish_date = indexes.DateField(model_attr='publish_date')
isbn = indexes.CharField(model_attr='isbn', null=True)
def get_model(self):
return Book
该类有一个方法 named get_model(),该方法指定我们要为哪个模型创建索引。
使用 Haystack,我们可以使用单一目录或多个目录来存储索引。索引目录是一个包含单个配置的目录,该配置指定 Elasticsearch、Solr 或 Whoosh 后端,它应存储索引数据。
我们需要在 search_indexes.py 文件中添加以下内容来定义索引目录:
# search_indexes.py
import os
from django.conf import settings
from django.utils.text import slugify
from django.template import loader
from haystack import indexes
from .models import Book
class BookIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
author = indexes.CharField(model_attr='author')
publish_date = indexes.DateField(model_attr='publish_date')
isbn = indexes.CharField(model_attr='isbn', null=True)
def get_model(self):
return Book
def prepare(self, obj):
prepared_data = super(BookIndex, self).prepare(obj)
prepared_data['boost'] = 1.0
prepared_data['slug'] = slugify(prepared_data['title'])
return prepared_data
def get_stored_fields(self, data, *args, **kwargs):
return ['title', 'author', 'publish_date', 'isbn', 'slug']
def index_queryset(self, using=None, **kwargs):
return self.get_model().objects.all()
上述代码使用 use_templates=True 参数使 Haystack 使用模板系统将文本字段的多个字段合并为一个字段。具体来说,它使用一个名为 'search/indexes/foo/bar_text.txt' 的模板文件,该文件类似于以下内容:
{% autoescape off %}{{ object.title }}{{ object.author }}{{ object.publish_date }}{{ object.isbn }}{{ object.description }}{% endautoescape %}
接下来,我们将介绍如何在 Django Haystack 中实现关键词高亮功能。
4. Django Haystack 实现关键词高亮
要对搜索结果进行关键词高亮,可以使用 Elasticsearch 或 Solr 这样的后端。对于 Whoosh 后端,关键词高亮功能不可用。
要启用关键词高亮功能,需要添加以下设置:
# settings.py
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
HAYSTACK_CONNECTIONS = {
# Solr
'default': {
'ENGINE': 'haystack.backends.solr_backend.SolrEngine',
'URL': 'http://localhost:8983/solr/default',
'INCLUDE_SPELLING': True,
'EXCLUDED_INDEXES': ['myapp.search_indexes.MyModelIndex'],
'SEARCH_RESULTS_PER_PAGE': 20,
'SILENTLY_FAIL': False,
'TIME_LIMIT': 120,
'INCLUDE_SCORES': True,
'BATCH_SIZE': 100,
'INCLUDE_FACETS': False,
'DJANGO_CT': 'text/plain',
},
# Elasticsearch
'elasticsearch': {
'ENGINE': 'haystack.backends.elasticsearch2_backend.Elasticsearch2SearchEngine',
'URL': 'http://localhost:9200/',
'INDEX_NAME': 'myapp',
'TIMEOUT': 60,
'INCLUDE_SPELLING': True,
'EXCLUDED_INDEXES': ['myapp.search_indexes.MyModelIndex'],
'SEARCH_RESULTS_PER_PAGE': 20,
}
}
注意:开启关键词高亮功能可能会影响性能。
现在,我们可以在模板文件中使用 highlight 参数,将需要高亮的内容包装在 <span> 标签中。有了这个参数,Elasticsearch 和 Solr 将使用它们的分析器来确定关键词位置,并将关键词包装在 <em> 或其他标记中。在我们的模板中,这会将搜索结果的所有匹配强调显示。
在索引中添加关键字高亮:
# search_indexes.py
from haystack import indexes
from .models import Book
class BookIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
author = indexes.CharField(model_attr='author')
publish_date = indexes.DateField(model_attr='publish_date')
isbn = indexes.CharField(model_attr='isbn', null=True)
def get_model(self):
return Book
def prepare(self, obj):
prepared_data = super(BookIndex, self).prepare(obj)
prepared_data['boost'] = 1.0
prepared_data['title'] = obj.title
return prepared_data
上述代码中,我们使用本地变量来保存 SearchIndex.prepare() 的返回结果,并添加一个新字段,将其设置为 obj.title 的值,以便我们可以在模板中选择要高亮显示的文本。
现在,我们可以在搜索视图中配置 SearchQuerySet,以便解析接受的搜索查询并突出显示文本:
# views.py
from django.shortcuts import render
from haystack.query import SearchQuerySet
def search(request):
query = request.GET.get('q', '')
sqs = SearchQuerySet().highlight().auto_query(query)
context = {
'query': query,
'sqs': sqs,
}
return render(request, 'search.html', context)
注意:我们在 SearchQuerySet 上调用 highlight() 方法,以便启用突出显示。该方法在 QuerySet API 中是唯一的对象,而不是链式方法。如果我们希望进一步修改查询,可以使用类似于 Django 中 QuerySet 的方法。
现在,我们只需要创建一个搜索模板来显示搜索结果,并使用 Haystack 提供的模板标记来渲染突出显示文本。
在模板中显示关键字高亮:
{% extends "base.html" %}
{% block title %}
Search Results | {{ block.super }}
{% endblock %}
{% block content %}
<form method="get" action="{% url 'search' %}">
<input name="q" type="text" />
<button type="submit">Search</button>
</form>
<ul>
{% for result in sqs %}
<li><a href="{{ result.object.get_absolute_url }}">{{ result.object.title }}</a> ({{ result.rank|floatformat }})</li>
{% for hl in result.highlighted %}
<ul>
{% for text in hl|safe %}
<li>{{ text|safe }}</li>
{% endfor %}
</ul>
{% endfor %}
{% empty %}
<p>No results found.</p>
{% endfor %}
</ul>
{% endblock %}
在模板中,模板标记 {% for hl in result.highlighted %} 是一个迭代,它包含突出显示的所有文本块,其中 hl 是每个文本块的变量名。
我们可以使用 safe 过滤器将文本字符串中的 HTML 转义默认值取消,以显示突出显示的文本。
5. 总结
在本文中,我们介绍了 Django Haystack 的基础知识以及如何创建搜索索引和实现关键词高亮功能。 Haystack 是一个非常强大的工具,允许我们使用各种后端搜索解决方案,包括 Elasticsearch、Solr 和 Whoosh。此外,它还提供了许多有用的工具和实用程序,使我们可以更轻松地实现复杂的搜索。