Django - 开发站点

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

2019-04-20  本文已影响0人  AllenBigBear

上一章记录了通过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/\<model_name>_text.txt这样的路径下需要创建以上格式的txt文件以存放你需要自定义的搜索区域。

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

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

3: 路由URL配置

在项目的urls里面设置如下

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

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

4:前端页面

主页上面写的搜索输入框

<form role="search" class="col" action="{% url 'haystack_search' %}" method="get">
      <input type="search" placeholder="请输入想要搜索的内容" name="q">
      <button type="submit">搜索</button>
  </form>

设置的search.html前端页面

    {% if query %}
        <h3>搜索结果如下</h3>
        {% for result in page.object_list %}
            <a href="{{ result.object.get_absolute_url }}">{{result.object.article_title}}</a>
    {% empty %}
        <p>No result found.</p>
        {% endfor %}

        {% if page.has_previous or page.has_next %}
                <div>
                    {% if page.has_previous %}<a href="?q={{ query }}&amp;page={{ page.previous_page_number }}">{% endif %}&laquo; Previous{% if page.has_previous %}</a>{% endif %}
                    |
                    {% if page.has_next %}<a href="?q={{ query }}&amp;page={{ page.next_page_number }}">{% endif %}Next &raquo;{% if page.has_next %}</a>{% endif %}
                </div>
        {% endif %}
    {% else %}
        <h>请输入关键字</h>
    {% 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:效果图

搜索关键字 搜索结果

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

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

上一篇 下一篇

猜你喜欢

热点阅读