Django NBA Web开发 - Step 11 全文搜索功能 haystack

上一章记录了通过model自带的搜索接口功能实现简单的搜索。
这一章节,来写一下通过第三方应用包来做到的高级全文搜索.
我们需要用到的应用是django-haystack

1: 安装应用

首先安装django-haystack,切记安装以后再setting里面设置的时候,把他设置在你自定义的所有app之前。

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'haystack',  #在所有app的首个
    'mainsite',
    'team',
    'users',
    'likes',
    'test_area',
    'mdeditor',
    'crispy_forms',

]

除了上面的配置,还需要在settings文件里设置如下

HAYSTACK_CONNECTIONS = {
    'default': {
        'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
        'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
    },
}
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 10
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

接着再安装相关的一些依赖包

Whoosh。Whoosh 是一个由纯 Python 实现的全文搜索引擎,没有二进制文件等,比较小巧,配置简单方便。

jieba 中文分词。由于 Whoosh 自带的是英文分词,对中文的分词支持不是太好,所以使用 jieba 替换Whoosh 的分词组件。

2:进行数据设定

打个比方,我的应用里,有一个model是Article,代表的是所有用户发布的文章
我现在想对这个内容进行搜索,我想搜索“abc”,但是不仅包括搜索文章标题,还想要把文章内容里包含“abc”的article找出来。
Article这个model属于我的项目里的mainsite这个app,需要我们在这个app下面创建如下文件search_indexes.py
而内容,则是写为如下

from haystack import indexes
from .models import Article,Team

class ArticleIndex(indexes.SearchIndex,indexes.Indexable):
    #一个索引类里,必须要有也只能有一个字段,设置为document=True,use_template=True
    text = indexes.CharField(document=True,use_template=True)

    def get_model(self):
        return Article

    def index_queryset(self, using=None):
        return self.get_model().objects.all()

这个类的命名是有规则的,是Modename + Index组成的
document=True意味着搜索引擎将以这个字段的内容来进行检索.
user_template=True意味着你可以在下面将会提到的索引文件.txt中自定义你想要搜索的区域,比如同时在内容和标题里搜索。
所以我们在templates/search/indexes/youapp/\_text.txt这样的路径下需要创建以上格式的txt文件以存放你需要自定义的搜索区域。

{{ object.article_title }}
{{ object.article_content }} 

这样就表示我想在标题和内容里同时搜索我输入的关键字

3: 路由URL配置

在项目的urls里面设置如下

urlpatterns = [
    ......
    path('search/',include('haystack.urls')),
]

千万记得不要在自己的app里设置search这个路由path了

4:前端页面

主页上面写的搜索输入框


设置的search.html前端页面

    {% if query %}
        

搜索结果如下

{% for result in page.object_list %} {{result.object.article_title}} {% empty %}

No result found.

{% endfor %} {% if page.has_previous or page.has_next %}
{% if page.has_previous %}{% endif %}« Previous{% if page.has_previous %}{% endif %} | {% if page.has_next %}{% endif %}Next »{% if page.has_next %}{% endif %}
{% endif %} {% else %} 请输入关键字 {% endif %}

在主页的搜索输入框前端页面这里踩了个巨坑,所有东西都调试完了,搜索以后就是没有结果显示,查看了代码,发现是{% if query %}这个条件没有满足,查看文档,发现query这个变量其实是用户输入的查询关键字,但是我明明已经输入了,但是为什么没有呢?
曾经尝试把method更改为post,也没有用,后来我想是不是取值没有取到,结果去haystack的源码一看,竟然他的取值是取得name=q的内容,如下。

    def get_query(self):
        """
        Returns the query provided by the user.

        Returns an empty string if the query is invalid.
        """
        if self.form.is_valid():
            return self.form.cleaned_data['q']

        return ''

我之前在写输入框的时候,name写的是“search_info”,现在改为q以后,马上就生效了。

5:效果图

Django NBA Web开发 - Step 11 全文搜索功能 haystack_第1张图片
搜索关键字
Django NBA Web开发 - Step 11 全文搜索功能 haystack_第2张图片
搜索结果

6:搜索结果URL问题

最后,还碰到一个小问题,就是搜索出来的结果,超链接的地址是不对的,他连接的是 http://127.0.0.1:8000/search/?q=function
而非每篇文章的页面,问题出在哪里呢?
出在get_absolute_url这个方法上,因为我们其实没有定义过get_absolute_url这个方法,故我们去Article这个模型中去定义。

class Article(models.Model):
  ......
    def get_absolute_url(self):
        return reverse('team:article_detail',args=[str(self.article_id)])

于是,就让搜索结果指向了模型案例本身页面。

这样,就大功告成了,这是英语的搜索,下一篇继续讲中文的搜索.

参考资料:
https://www.zmrenwu.com/courses/django-blog-tutorial/materials/27/
https://django-haystack.readthedocs.io/en/master/tutorial.html

你可能感兴趣的:(Django NBA Web开发 - Step 11 全文搜索功能 haystack)