Django Haystack 全文检索与关键词高亮

在此之前我们使用了 Django 内置的一些方法实现了一个简单的搜索功能。但这个搜索功能实在过于简单,没有多大的实用性。对于一个搜索引擎来说,至少应该能够根据用户的搜索关键词对搜索结果进行排序以及高亮关键字。现在我们就来使用 django-haystack 实现这些特性。

Django Haystack 简介

django-haystack 是一个专门提供搜索功能的 django 第三方应用,它支持 Solr、Elasticsearch、Whoosh、Xapian 等多种搜索引擎,配合著名的中文自然语言处理库 jieba 分词,就可以为我们的博客提供一个效s果不错的博客文章搜索系统。

安装必要依赖

要使用 django haystack,首先必须安装它,并且安装一些必要的依赖,具体需要安装的依赖有:

  • Whoosh。Whoosh 是一个由纯 Python 实现的全文搜索引擎,没有二进制文件等,比较小巧,配置简单方便。
  • jieba 中文分词。由于 Whoosh 自带的是英文分词,对中文的分词支持不是太好,所以使用 jieba 替换Whoosh 的分词组件。

直接使用 pip 安装这些包即可(安装到你使用的虚拟环境下):pip install whoosh django-haystack jieba

配置 Haystack

安装好 django haystack 后需要在项目的 settings.py 做一些简单的配置。

首先是把 django haystack 加入到 INSTALLED_APPS 选项里:

blogproject/settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    # 其它 app...
    'haystack',
    'blog',
    'comments',
]

然后加入如下配置项:

blogproject/settings.py

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

HAYSTACK_CONNECTIONSENGINE 指定了 django haystack 使用的搜索引擎,这里我们使用了 blog.whoosh_cn_backend.WhooshEngine,虽然目前这个引擎还不存在,但我们接下来会创建它。PATH 指定了索引文件需要存放的位置,我们设置为项目根目录 BASE_DIR 下的 whoosh_index 文件夹(在建立索引是会自动创建)。

HAYSTACK_SEARCH_RESULTS_PER_PAGE 指定如何对搜索结果分页,这里设置为每 10 项结果为一页。

HAYSTACK_SIGNAL_PROCESSOR 指定什么时候更新索引,这里我们使用 haystack.signals.RealtimeSignalProcessor,作用是每当有文章更新时就更新索引。由于博客文章更新不会太频繁,因此实时更新没有问题。

处理数据

接下来就要告诉 django haystack 使用那些数据建立索引以及如何存放索引。如果要对 blog 应用下的数据进行全文检索,做法是在 blog 应用下建立一个 search_indexes.py 文件,写上如下代码:

blog/search_indexes.py

from haystack import indexes
from .models import Post


class PostIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)

    def get_model(self):
        return Post

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

这是 django haystack 的规定。要相对某个 app 下的数据进行全文检索,就要在该 app 下创建一个 search_indexes.py 文件,然后创建一个 XXIndex 类(XX 为含有被检索数据的模型,如这里的 Post),并且继承 SearchIndexIndexable

为什么要创建索引?索引就像是一本书的目录,可以为读者提供更快速的导航与查找。在这里也是同样的道理,当数据量非常大的时候,若要从这些数据里找出所有的满足搜索条件的几乎是不太可能的,将会给服务器带来极大的负担。所以我们需要为指定的数据添加一个索引(目录),在这里是为 Post 创建一个索引,索引的实现细节是我们不需要关心的,我们只关心为哪些字段创建索引,如何指定。

每个索引里面必须有且只能有一个字段为 document=True,这代表 django haystack 和搜索引擎将使用此字段的内容作为索引进行检索(primary field)。注意,如果使用一个字段设置了document=True,则一般约定此字段名为text,这是在 SearchIndex 类里面一贯的命名,以防止后台混乱,当然名字你也可以随便改,不过不建议改。

并且,haystack 提供了use_template=True 在 text 字段中,这样就允许我们使用数据模板去建立搜索引擎索引的文件,说得通俗点就是索引里面需要存放一些什么东西,例如 Post 的 title 字段,这样我们可以通过 title 内容来检索 Post 数据了。举个例子,假如你搜索 Python ,那么就可以检索出 title 中含有 Python 的Post了,怎么样是不是很简单?数据模板的路径为 templates/search/indexes/youapp/\<model_name>_text.txt(例如 templates/search/indexes/blog/post_text.txt),其内容为:

templates/search/indexes/blog/post_text.txt

{{ object.title }}
{{ object.body }}

这个数据模板的作用是对 Post.title、Post.body 这两个字段建立索引,当检索的时候会对这两个字段做全文检索匹配,然后将匹配的结果排序后作为搜索结果返回。

配置 URL

接下来就是配置 URL,搜索的视图函数和 URL 模式 django haystack 都已经帮我们写好了,只需要项目的 urls.py 中包含它:

blogproject/urls.py

urlpatterns = [
    # 其它...
    url(r'^search/', include('haystack.urls')),
]

另外在此之前我们也为自己写的搜索视图配置了 URL,把那个 URL 删掉,以免冲突:

blog/urls.py

# url(r'^search/$', views.search, name='search'),

修改搜索表单

修改一下搜索表单,让它提交数据到 django haystack 搜索视图对应的 URL:

<form role="search" method="get" id="searchform" action="{% url 'haystack_search' %}">
  <input type="search" name="q" placeholder="搜索" required>
  <button type="submit"><span class="ion-ios-search-strong"></span></button>
</form>

主要是把表单的 action 属性改为 {% url 'haystack_search' %}

创建搜索结果页面

haystack_search 视图函数会将搜索结果传递给模板 search/search.html,因此创建这个模板文件,对搜索结果进行渲染:

templates/search/search.html

{% extends 'base.html' %}
{% load highlight %}

{% block main %}
    {% if query %}
        {% for result in page.object_list %}
            <article class="post post-{{ result.object.pk }}">
                <header class="entry-header">
                    <h1 class="entry-title">
                        <a href="{{ result.object.get_absolute_url }}">{% highlight result.object.title with query %}</a>
                    </h1>
                    <div class="entry-meta">
                    <span class="post-category">
                        <a href="{% url 'blog:category' result.object.category.pk %}">
                            {{ result.object.category.name }}</a></span>
                        <span class="post-date"><a href="#">
                            <time class="entry-date" datetime="{{ result.object.created_time }}">
                                {{ result.object.created_time }}</time></a></span>
                        <span class="post-author"><a href="#">{{ result.object.author }}</a></span>
                        <span class="comments-link">
                        <a href="{{ result.object.get_absolute_url }}#comment-area">
                            {{ result.object.comment_set.count }} 评论</a></span>
                        <span class="views-count"><a
                                href="{{ result.object.get_absolute_url }}">{{ result.object.views }} 阅读</a></span>
                    </div>
                </header>
                <div class="entry-content clearfix">
                    <p>{% highlight result.object.body with query %}</p>
                    <div class="read-more cl-effect-14">
                        <a href="{{ result.object.get_absolute_url }}" class="more-link">继续阅读 <span
                                class="meta-nav"></span></a>
                    </div>
                </div>
            </article>
        {% empty %}
            <div class="no-post">没有搜索到你想要的结果!</div>
        {% 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 %}
        请输入搜索关键词,例如 django
    {% endif %}
{% endblock main %}

这个模板基本和 blog/index.html 一样,只是由于 haystack 对搜索结果做了分页,传给模板的变量是一个 page 对象,所以我们从 page 中取出这一页对应的搜索结果,然后对其循环显示,即 {% for result in page.object_list %}。另外要取得 Post(文章)以显示文章的数据如标题、正文,需要从 result 的 object 属性中获取。query 变量的值即为用户搜索的关键词。

高亮关键词

注意到百度的搜索结果页面,含有用户搜索的关键词的地方都是被标红的,在 django haystack 中实现这个效果也非常简单,只需要使用 {% highlight %} 模板标签即可,其用法如下:

# 使用默认值  
{% highlight result.summary with query %}  

# 这里我们为 {{ result.summary }} 里所有的 {{ query }} 指定了一个<div></div>标签,并且将class设置为highlight_me_please,这样就可以自己通过CSS为{{ query }}添加高亮效果了,怎么样,是不是很科学呢  
{% highlight result.summary with query html_tag "div" css_class "highlight_me_please" %}  

# 可以 max_length 限制最终{{ result.summary }} 被高亮处理后的长度
{% highlight result.summary with query max_length 40 %}  

在博客文章搜索页中我们对 title 和 body 做了高亮处理:{% highlight result.object.title with query %},{% highlight result.object.body with query %}。高亮处理的原理其实就是给文本中的关键字包上一个 span 标签并且为其添加 highlighted 样式(当然你也可以修改这个默认行为,具体参见上边给出的用法)。因此我们还要给 highlighted 类指定样式,在 base.html 中添加即可:

base.html

<head>
    <title>Black &amp; White</title>
    ...
    <style>
        span.highlighted {
            color: red;
        }
    </style>
    ...
</head>

修改搜索引擎为中文分词

我们使用 Whoosh 作为搜索引擎,但在 django haystack 中为 Whoosh 指定的分词器是英文分词器,可能会使得搜索结果不理想,我们把这个分词器替换成 jieba 中文分词器。从你安装的 haystack 中把 haystack/backends/whoosh_backends.py 文件拷贝到 blog/ 下,重命名为 whoosh_cn_backends.py(之前我们在 settings.py 中 的 HAYSTACK_CONNECTIONS 指定的就是这个文件),然后找到如下一行代码:

schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=StemmingAnalyzer(), field_boost=field_class.boost, sortable=True)

将其中的 analyzer 改为 ChineseAnalyzer,当然为了使用它,你需要在文件顶部引入:from jieba.analyse import ChineseAnalyzer。

from jieba.analyse import ChineseAnalyzer

...
#注意先找到这个再修改,而不是直接添加  
schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=ChineseAnalyzer(),field_boost=field_class.boost, sortable=True)  

建立索引文件

最后一步就是建立索引文件了,运行命令 python manage.py rebuild_index 就可以建立索引文件了。

来看看搜搜效果吧,效果还不错。

django haystack搜索结果

总结

本章节的代码位于:Step26: full text search using django haystack

如果遇到问题,请通过下面的方式寻求帮助。

后记

结束了么?是的,Django 博客开发教程系列在这里全部结束了,感谢大家的阅读和反馈!

But...这只是个开始,技术开发学无止境,Django 还有很多更加高级的特性等我们去学习和探索。所以,请关注我的 个人博客 和加入 Pythonzhcn 社区,让我们在 Python 学习的路上共同进步。

资源整理与汇总

-- EOF --


158 条评论 / 84 人参与
startlearner

ImportError: No module named 'haystack.singals'

有没有小伙伴遇到这个错误的?

自己搜了下没有将这个问题的啊?

版本从1.10直接升级到了目前的最新版Django2.1版本后按照底下评论的朋友把Django换成1.10.6,并把

django-haystack换成了2.6.0,怎么还会带入错误啊?


追梦人物 [博主] startlearner

去 haystack 下看看 signals.py 是否存在?极可能是版本问题。


startlearner 追梦人物 [博主]

我看了下haystack是有signals这个文件的,然后我尝试重装了下django-haystack==2.6.0版本的,发现Requirement already satisfied: Django<1.11,按照道理我django安装的1.10.6符合要求应该兼容的啊


wengmei

请问我的HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'为什么删除数据,索引没有删除,但是更新和修改是可以同步的


个人开发者

#修改搜索引擎为中文分词

从你安装的 haystack 中把 haystack/backends/whoosh_backends.py 文件拷贝到 blog/ 下,重命名为 whoosh_cn_backends.py

这里是个坑,博主文件命名是whoosh_cn_backends.py,但在:

blogproject/settings.py 

HAYSTACK_CONNECTIONS = { 'default': { 'ENGINE': 'blog.whoosh_cn_backend.WhooshEngine', 'PATH': os.path.join(BASE_DIR, 'whoosh_index'), },}

中引用的是没有whoosh_cn_backend,名字引用不对,导致掉坑到晚上1点多都没解决,但在博主的源代码中是用的whoosh_cn_backend命名,可能是写博客的时候写错了,希望博主改一下。


whutlhc 个人开发者

其实没有关系,是写的有点问题,但是你直接去安装的底下找了拷贝的haystack/backends/whoosh_backend.py 后面是没有s的,所以直接拷贝过去也是对的呀。


Copperfie1d

已经做好了,现在有个小问题,就是手机访问时,右上方的首页、博客、关于、联系几个链接会变成一个三横的小图标,但是不能点,查了一下好像是css的问题,有没有什么解决方案呢?


downdawn

有没有人直接克隆到本地上运行的?代码没什么问题,可以运行成功,不过打开的博客和后台很卡很卡,动不了。。。


downdawn downdawn

解决了


MarkHoo

pip install whoosh django-haystack jieba    复制安装后,版本从1.10直接升级到了目前的最新版Django2.1版本。这是怎么回事???是不是你打错少了逗号,应该是pip install whoosh, django-haystack, jieba


追梦人物 [博主] MarkHoo

怀疑是 django-haystack 的原因,卸载 django 再重新指定 1.10 版本安装 django 吧


nkyiming 追梦人物 [博主]

请问博主应该安装哪个版本的 django-haystack ?我从 1.2.x 一直试,都有各种无法 import 某些模块的 error


nkyiming nkyiming

目前安装 django-haystack 2.6.0 版本是可以兼容 1.10.6


startlearner nkyiming

我按照你的版本号配的django1.10.6和django-haystack2.6.0还是出现问题了,报错ImportError: No module named 'haystack.singals',按照楼主给的意见看了下haystack是有singals这个文件的,版本如果不对的话请问当时没有问题吗?怎么解决的?


半夏的距离

报错Reverse for 'search' not found. 'search' is not a valid view function or pattern name.

在这段代码的跳转中有问题,为什么啊

<form role="search" method="get" id="searchform" action="{% url  'haystack_search' %}"> 63                            <input type="search" name='q' placeholder="搜索" required> 64                             

<button type="submit"><span class="ion-ios-search-strong"></span></button> 65                       

  </form>


半夏的距离 半夏的距离

前边的报错打错了,是这个Reverse for 'haystack_search' not found. 'haystack_search' is not a valid view function or pattern name.


fuweifu-vtoo/jonathan 半夏的距离

和你一样的错误,最后解决了,期间尝试过更换haystack的版本,尝试过在py文件中from XXX import reverse等,都没效果,最后重新看了一遍教程,发现:

我是在blog的urls.py文件中添加的url(r'^search/',include('haystack.urls')),这一行代码,而博主是在blogproject的urls.py文件中添加的url(r'^search/',include('haystack.urls'))。改正之后就解决了。


suyufeilong

ModuleNotFoundError: No module named 'blog.whoosh_cn_backend'

为什么会这样,代码一样


suyufeilong suyufeilong

搞定了


xiaopanddxiong suyufeilong

你是怎么解决的?也遇到这个问题了


sjllllllllll xiaopanddxiong

在settings里面将whoosh的引擎改为这个haystack.backends.whoosh_backend.WhooshEngine;去掉cn就不报错了


suyufeilong

django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty.

这种问题怎么解决


-Ni

博主请问下能否用django开发一个多用户支持的博客,像CSDN和博客园那样.


追梦人物 [博主] -Ni

可是可以的,但是挺复杂,自行探索吧


WEI丶weiksjsks

请问博主怎么会出现:WARNING: This will irreparably remove EVERYTHING from your search index in connection 'default'.Your choices after this are to restore from backups or rebuild via the `rebuild_index` command.Are you sure you wish to continue? 这种问题?


追梦人物 [博主] WEI丶weiksjsks

不知道怎么回事,你可以根据信息在 google 上搜索相关的问题。


张小二_tiny

所有功能全部实现了。也学到不少东西。但还是感觉处于迷茫状态。。。


追梦人物 [博主] 张小二_tiny

接下来需要自己思考了,看别人的东西永远都是别人的。


Chekoo

感谢博主,学到了挺多。


独步灵骑

博主您好 为什么我装上Django Haystack 再启动服务器就会出现
Unhandled exception in thread started by <function check_errors.<locals>.wrapper at 0x00000286D841C950>Traceback (most recent call last):  File "C:\Users\kahn\Envs\blogproject_env\lib\site-packages\django\utils\autoreload.py", line 225, in wrapper    fn(*args, **kwargs)  File "C:\Users\kahn\Envs\blogproject_env\lib\site-packages\django\core\management\commands\runserver.py", line 112, in inner_run    autoreload.raise_last_exception()  File "C:\Users\kahn\Envs\blogproject_env\lib\site-packages\django\utils\autoreload.py", line 248, in raise_last_exception    raise _exception[1]  File "C:\Users\kahn\Envs\blogproject_env\lib\site-packages\django\core\management\__init__.py", line 327, in execute    autoreload.check_errors(django.setup)()  File "C:\Users\kahn\Envs\blogproject_env\lib\site-packages\django\utils\autoreload.py", line 225, in wrapper    fn(*args, **kwargs)  File "C:\Users\kahn\Envs\blogproject_env\lib\site-packages\django\__init__.py", line 24, in setup    apps.populate(settings.INSTALLED_APPS)  File "C:\Users\kahn\Envs\blogproject_env\lib\site-packages\django\apps\registry.py", line 112, in populate    app_config.import_models()  File "C:\Users\kahn\Envs\blogproject_env\lib\site-packages\django\apps\config.py", line 198, in import_models    self.models_module = import_module(models_module_name)  File "C:\Users\kahn\Envs\blogproject_env\lib\importlib\__init__.py", line 126, in import_module    return _bootstrap._gcd_import(name[level:], package, level)  File "<frozen importlib._bootstrap>", line 994, in _gcd_import  File "<frozen importlib._bootstrap>", line 971, in _find_and_load  File "<frozen importlib._bootstrap>", line 955, in _find_and_load_unlocked  File "<frozen importlib._bootstrap>", line 665, in _load_unlocked  File "<frozen importlib._bootstrap_external>", line 678, in exec_module  File "<frozen importlib._bootstrap>", line 219, in _call_with_frames_removed  File "C:\Users\kahn\Workspace\blogproject\blog\models.py", line 41, in <module>    class Post(models.Model):  File "C:\Users\kahn\Workspace\blogproject\blog\models.py", line 71, in Post    category = models.ForeignKey(Category)TypeError: __init__() missing 1 required positional argument: 'on_delete'

这样的报错?

怎么解决啊 不胜感激


追梦人物 [博主] 独步灵骑

报错已经提示你了,django 2.0 请给 field 加上必要的 on_delete 参数,具体请参考 2.0 官方文档。


azunia

装上面的依赖。。。自动把我的django1.10.6卸了,升级成2.0.5了。。怎么破。。Image


azunia azunia

有没有haystack老版本号呢,直接装它是2.8.1版本的。需要django>=1.11

他就把1.10.6卸了。。装了2。0.5

有没有haystack支持1.10.6的版本?


追梦人物 [博主] azunia

你看 haystack 文档的版本介绍咯,可以使用 pip install package==x.x 来指定版本号的。


白色的小方块

运行命令 python manage.py rebuild_index后,选择y后报错:

haystack.exceptions.SearchBackendError: No fields were found in any search_indexes. Please correct this before attempting to search.

全部按照博主的做,评论区的也看了,还是解决不了,没办法了,看看后面的有没有高人指点了


白色的小方块 白色的小方块

然后我先跳过这个错误试着运行博客,首页能进,搜索时报错:

No fields were found in any search_indexes. Please correct this before attempting to search.


suxianglun 白色的小方块

看一下你的search_indexes.py文件命名是否正确,以及位置是否正确,我遇到和你一样的问题,后来排查一下,是命名没有严格按照search_indexes.py命名,希望能帮助到你


岩先森丶丿

执行最后一步python manage.py rebuild_index出错

ImportError:cannot import name 'connections'

大神们是怎么解决的.谢谢


岩先森丶丿 岩先森丶丿

一开始 haystack import connections失败

重新安装了一遍 django-haystack 就能import成功了


ABC_什么才不会被占用

settings配置如下:

HAYSTACK_CONNECTIONS = {    'default': {       

 'ENGING': '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'


./manage.py rebuild_index运行结果如下:

WARNING: This will irreparably remove EVERYTHING from your search index in connection 'default'.Your choices after this are to restore from backups or rebuild via the `rebuild_index` command.Are you sure you wish to continue? [y/N] Removing all documents from your index because you said so./home/tarena/my_env/env3.5/lib/python3.5/site-packages/haystack/backends/simple_backend.py:47: UserWarning: clear is not implemented in this backend  warn('clear is not implemented in this backend')All documents removed.

求解答,谢谢!


scrapy
希望能及时更新博客,想看看分层评论是如何写!

wishd

执行python manage.py rebuild_index后出现如下错误,如何解决

SystemCheckError: System check identified some issues: 

 ERRORS: 

blog.Post.author: (fields.E312) The to_field 'True' doesn't exist on the related model 'auth.User'.blog.Post.category: (fields.E312) The to_field 'True' doesn't exist on the related model 'blog.Category'.comments.Comment.post: (fields.E312) The to_field 'True' doesn't exist on the related model 'blog.Post'.


pyli.xm

test


huangjing2016

博主,在全文搜索视线中发现一个问题,就是搜索数字时都无法搜索想要的结果,请问是什么原因呢

ps 下载了示例代码运行也是一样


追梦人物 [博主] huangjing2016

这个搜索引擎只能实现基本功能,没法做到精细。精细的话你可以考虑使用其它功能更加完善的搜索引擎。


sunsc11

关于关键字高亮时,标题中前面的字体被"..."取代,有一个较简答的做法,在源码中添加两行语句就行了。源码位置为:你的虚拟环境/Lib/site-packages/haystack/utils/highlighting.py,直接找到最后面,加入两行判断长度的代码:

if len(self.text_block) < self.max_length:   #新增加的判断语句,用来判断文本长度
return self.text_block #如果不足max_length,就直接返回
if start_offset > 0:
highlighted_chunk = '...%s' % highlighted_chunk
if end_offset < len(self.text_block):
highlighted_chunk = '%s...' % highlighted_chunk

return highlighted_chunk

原理很简单,就是如果文本长度不足max_length(默认200),就直返回该文本。当然,这只是个偷巧的办法,因为我们在创建博客时,一般博客的标题都会限定长度,不会超过200的。


sunsc11 sunsc11

额。。。汗颜了,发现效果达到了,但是高亮没了。。。

把那两句代码改成如下就可以了:

if len(self.text_block) < self.max_length:  
return self.text_block[:start_offset] + highlighted_chunk

scrapy sunsc11

我也发现了这个问题,按照你提供的方法修改了源码

没有再出现这个....问题


1Tian-zhang

博主你好,我是在找Django 博客主题和前端UI的时候,从 http://www.python88.com/topic/1737 上跳转过来的....被吸引过来点开之后,发现博主的界面特别简洁漂亮...一秒圈粉....(设计审美能力大赞 !!!)。

按照教程一步步走下来之后,发现还是有一点小不同的,后来在GitHub上找到了博客完整版的代码。想请问博主:我可以应用你的代码,搭建出自己的博客吗 ?(并绝对会 在底部标明,是来源于博主这里,同时加上跳转链接) .....不知道是否需要授权,或者有什么需要备注一下的。


追梦人物 [博主] 1Tian-zhang

都是开源的,你可以随意地复制、修改、传播。


1Tian-zhang 追梦人物 [博主]

感谢博主感谢博主~~


EminJaaaN

博主你好,

ImportError: No module named 'blog.whoosh_cn_backend'

报错了,该怎么办


EminJaaaN EminJaaaN

已解决,谢谢各位


用户6452171002 EminJaaaN

您好,我也出现了同样的问题 请问您是怎么解决的


Eminjan 用户6452171002

少写了一个s 在下方评论也有类似问题的解答 ,你可以参考一下


NOT__SURE

博主,请问根据步骤,最后调用生成index的命令python manage.py rebuild_index会报错,

TypeError: Unknown option(s) for clear_index command: batchsize, workers. Valid options are: commit, help, interactive, no_color, nocommit, noinput, pythonpath, settings, skip_checks, stderr, stdout, traceback, using, verbosity, version.

google也没什么结论。最后看了下haystack的文档,里面有个note

Using the standard SearchIndex, your search index content is only updated whenever you run either ./manage.py update_index or start afresh with ./manage.py rebuild_index.

然后我使用./manage.py update_index 这个命令生成了index,请问这两者区别是什么?


不言寂寞666 NOT__SURE

咱俩问题一模一样啊,不知道什么问题


guanfeix NOT__SURE

我也是出现这样的问题,windows10,django2.0,python 3


小Q营姐 NOT__SURE

问题一样,请问层主找到解决方法了不


qiaominghe

花了两周的时间看完了整套博客,真心的向作者说一声谢谢啦~


追梦人物 [博主] qiaominghe

不客气的,对你有帮助就好!


宋逸雪da

我弄好之后,只有搜索对象的全名才能搜出结果,搜对象的字段就出不来,比如搜我现在的商品模型,搜‘甲鱼’就能出来,但是搜‘’鱼‘’就没有结果,搜商品描述字段中的文字也出不来,这是怎么回事?


loveroot 宋逸雪da

确实,应该是中文分词的问题,把一个词语拆开就无法搜索到。


Simoral

[问题]:

执行操作:

python manage.py rebuild_index

时报错,错误内容:

File "D:\project\CodePython\blog\lib\site-packages\haystack\admin.py", line 13, in <module>    from haystack import connectionsImportError: cannot import name 'connections'


Simoral Simoral

谁能帮忙回答一下,谢谢,不胜感激


Simoral Simoral

pip 安装包后不要忘记更新 requirements.txt 文件,不然部署到服务器上会报错

```python

pip freeze >requirements.txt

```


jing.wang Simoral

同样遇到这个问题 怎么解决的?


Learning Html Notes jing.wang

我也遇到了  

from haystack import connections 

ImportError: cannot import name 'connections',

请问有人解决了吗


追梦人物 [博主] Learning Html Notes

我想知道大家是怎么解决这个问题的?


floatval 追梦人物 [博主]

出现这个问题的原因一般是安装了 haystack,我是直接卸载了haystack,然后安装django-haystack后搞定的


岩先森丶丿 Simoral

请问这个问题解决了吗 我也遇到了试了几遍也不行!!


岩先森丶丿 floatval

我安装的就是django-haystack还是报这个错...


Zhai Xuyan 追梦人物 [博主]

博主,这个haystack 是不支持django2.0以上的吗,我在它的官网上好像也没有找到对应的版本,直接pip install haystack 的话,会自动帮我卸载django2.0 ,然后安装django1.10 的版本


追梦人物 [博主] Zhai Xuyan

哦也不清楚,应该是吧


dragon1061


[图片]

执行 python manage.py rebuild_index的时候出现错误


xqyxqy

感谢楼主,跟完博客了,还是有点蒙蒙的,重新回看几遍。


Stallionshell

博主 你好 我按照本章内容添加后, 出现了如下错误

Image

但是我并没有修改index.html文件 而且即使我删除红字 报错语句仍然出现错误,更绝望的是,我做之前忘了git保存进度,我一一删去之后新添加内容之后 回到之前的初始状态,则出现

Image

绝望。。。。。。


Stallionshell Stallionshell

图片链接有误,

依次是Image

以及删除之后的

Image


Stallionshell Stallionshell

早上起来再查了一下stackoverflow,可能是urls.py的问题 但我对比了一下和博主的源码 除了注释掉之前的simple search的url并没有什么额外的改动,而且出现的报错在一个莫名其妙的位置 还是让人头疼。

出错的代码地址是 

https://github.com/Luxiaowuu/blog/tree/failed_haystack 

其中blogproject对应的是web_blog 其他大致一致。如果博主有空能帮忙看一下 不胜感激。


Stallionshell Stallionshell

折腾了一上午,我似乎解决了一部分,首先我在尝试这个章节的时候,我只是把之前的simple search注释掉,包括在templates中的代码。然而因为我在打开首页index的时候出现问题,应该是base.html的问题 因此我试着删掉了之前的simple search的内容而不是单纯的注释掉,然后解决了。  但不知道是为什么。


杰木四水

对着学了一遍,代码基本可以默下来了。受益匪浅!感谢!


bolianlai

这教程真心不错,讲解的是我看到的最详细的了。


YY饺子

博主,当我尝试删除导航栏上的关于,联系等,并增加其他方块的URL时,直接在base.html更改后,我发现只有pc端可以正常显示效果,在移动端上,被删除的关于联系依然存在,其它的URL连接也没有生效,请问这是不是需要更改前端模版呢,改怎么样解决这个问题?


追梦人物 [博主] YY饺子

为了良好的响应式,移动端的导航栏是另外的代码,你在模板中找一下添加上去即可。


YY饺子 追梦人物 [博主]

可是我找不出移动端的模版文件。。它是属于html吗,还是说通过js等语言适配的移动端?,我实在是不懂前端这些。


YY饺子 追梦人物 [博主]

不用了不用了,我找到啦!!


Annihilater

感谢博主,教程做完受益匪浅,很详细!!!


Hwan

博主,我最后一步出现问题,ModuleNotFoundError: No module named 'haystackblog',请问这是什么原因呢?


追梦人物 [博主] Hwan

没有 haystackblog.py 这个模块。具体你检查下哪行代码的问题。


MyGodot Hwan

我也遇到同样的问题,INSTALLED_APPS = [ ... 'blog', 'comments', 'haystack',]中的'comments'与'haystack'注意用逗号隔开,就好了,希望能帮到你。


MyGodot MyGodot

你的情况应该把blog与haystack用逗号隔开


xiaopoly

博主,按照您的方法配置后,我搜素时出现

UnicodeDecodeError at /search/ 

'utf-8' codec can't decode byte 0xc6 in position 1252: invalid continuation byte

Request Method:GET

 Request URL:http://127.0.0.1:8000/search/?q=%E6%B5%8B%E8%AF%95

 Django Version:1.11.5 

Exception Type:UnicodeDecodeError

 Exception Value:'utf-8' codec can't decode byte 0xc6 in position 1252: invalid continuation byte

 Exception Location:A:\Code\BlogProject\lib\codecs.py in decode, line 321

 Python Executable:A:\Code\BlogProject\Scripts\python.exe

 Python Version:3.6.1

 Python Path:['A:\\Workspace\\blogproject', 'A:\\Code\\BlogProject\\Scripts\\python36.zip', 'A:\\Code\\BlogProject\\DLLs', 'A:\\Code\\BlogProject\\lib', 'A:\\Code\\BlogProject\\Scripts', 'a:\\python\\python36\\Lib', 'a:\\python\\python36\\DLLs', 'A:\\Code\\BlogProject', 'A:\\Code\\BlogProject\\lib\\site-packages'] 

Server time:星期五, 6 十月 2017 00:39:33 +0800

 Unicode error hintThe string that could not be encoded/decoded was: t }} ����</

请教如何解决?谢谢!


chenzhixiang1992

这个真好


zhanxiangyu

博主你的现在的评论系统怎么写的,可以进行层级回复功能?是集成三方社会系统吗?我的只能显示一层评论不够啊,


Tom

请问一下~~ 执行 python manage.py rebuild_index  以及  python manage.py runserver  报错 raise ImproperlyConfigured("The SECRET_KEY setting must not be empty.")django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty.这个怎么解决?

检查了setting.py 配置文件 ,SECRET_KEY  并不是为空~~~     

求指导~~


Tom Tom

补充说明: 已经完成了本节的配置,~配置的时候没有出什么错~~  最后运行代码~ 报上面的错,求怎么解决~~ 


Misengkang

真是感谢博主详细的教程 ,完全跟着走了一遍,感觉学到不少,自己改了点前端,终于搭建好了第一个博客:http://www.kangkangblog.site/


dlsafety Misengkang

你好,看了你的博客,很喜欢那个风格。可是我照着源码改,有几个地方没改出来。

请问尘埃和首页这些字怎么设计颜色的?

我改完的各个模块的背景是方的,请问圆角是在哪里设置的?

菜鸟一枚,问题可能很幼稚,希望不吝赐教,非常感谢。


mamami

博主还有新的教程没有,分享个链接呗


追梦人物 [博主] mamami

都在我博客上了


Hu Zhu

我在Google找了很久,没有找到想要的东西,所以在博主这边留个言,看看有没有解决办法。

问题:haystack + ajax如何使用,或者更细化的问题是,后台如何调用haystack只返回一串我想要的json?期待群主的回复,困住我一天了


追梦人物 [博主] Hu Zhu

haystack 的 search 视图函数返回的是一个 result query 对象,类似于 QuerySet,你可以覆写 search 视图函数,将返回的 result 序列化为 Json 格式后返回。


Hu Zhu 追梦人物 [博主]

抱歉,群主,我没有找到这个search视图函数。

django version:1.11.3 

haystack version:2.6.1.

劳烦群主说的详细一点.


loveroot Hu Zhu

whoosh_cn_backend.py 就是这个文件里面的search函数吧 返回的results


Yc1883896 Hu Zhu

表示遇到了同样的问题,难道haystack只能基于Django返回模板型response,不应该啊,总应该可以序列化为json的


追梦人物 [博主] Yc1883896

序列化应该要额外配置或者自己定义新的搜索视图。


badflockmaster

不管我搜索如何东西

都是显示标签empty下的内容

前端我复制了老师你的

但是还是错了

其他的文件我也都和老师你的源码进行了对比

也没有出错

不知道为啥,总是显示empty标签下的内容


badflockmaster badflockmaster

已经解决了,原因是因为我没有问搜索表单中的input控件中,没有添加name=q,添加之后就可以正常搜索了


刀杨毛
HAYSTACK_CONNECTIONS 里的 'ENGINE':'blog.whoosh_cn_backend.WhooshEngine', 少了个"s" ,whoosh_cn_backends

楼主原文: haystack/backends/whoosh_backends.py 文件拷贝到 blog/ 下,重命名为 whoosh_cn_backends.py

Annihilater 刀杨毛

没有少s,我做的时候没有whoosh_cn_backends、whoosh_backends这两个文件


吉超 刀杨毛

的确是少了个s,折腾了半天才发现


striderhcx
博主你好,请教一下
text = indexes.CharField(document=True, use_template=True),这个不是很理解,如果名字不是text,是其他,比如mytext,其他地方需要改吗?有什么地方以来这个名字?

追梦人物 [博主] striderhcx
文档中说 text 只是一个约定名称,可以改成其它的。关键是要有 document=True 的设置。

chenyufei91
博主你好- -
当我搜索的关键词如果出现在标题中, 他会自动将标题中的关键字放在最前面,然后之前的内容都变成省略号了。
例如:自动生成文章摘要
我搜索《生成》
出来的结果文章标题就变成了 ···生成文章摘要
请问这个问题怎么解决啊- -
谢谢啦啊- - 教程我点128个赞

追梦人物 [博主] chenyufei91
可以拓展 haystack 用于代码高亮的类,但是远超入门范围,所以我没有在文章讲解,自行研究吧。

dackzome
大佬,我用的django 1.11,Whoosh==2.7.4,django-haystack==2.6.1【都是最新版】,按照你的代码会报错【ImportError: No module named 'blog.whoosh_cn_backend'】。去看官方文档,http://django-haystack.readthedocs.io/en/master/tutorial.html#whoosh,【ENGINE】改成如下代码中的ENGINE才不会报错。希望给后来者借鉴【import os
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
'PATH': os.path.join(os.path.dirname(__file__), 'whoosh_index'),
},
}】

追梦人物 [博主] dackzome
看完教程你会发现没有错的。

qiaominghe dackzome

赞,我也遇到同样问题,用你的方法解决了~~~


Learning Html Notes dackzome

我也遇到同样的问题,使用你说的官方文档方法解决了


移云宝宝
博主,请问下添加 ChineseAnalyzer 后是否无法搜索数字了,我搜索中文英文均正常,但是搜索数字如电话号码就显示无结果。不知道该怎么解决,请教一下。谢谢。

移云宝宝 移云宝宝
刚看了下面其他的问题,部分的输入电话号码无结果,全部就有了。已经明白了,谢谢。

追梦人物 [博主] 移云宝宝
嗯,分词问题吧,因为博客对搜索精度要求不是太高,使用默认分词机制就好。

mozhemeng
博主,这个搜索的是数据库里存的有markdown代码的原文吗,但是这样的话,比如我搜索python ,因为我写markdown的时候,为了代码高亮都会在代码块的```后加python关键字,这样这个python也会被搜索进去,但其实这篇文章可能没有python这个关键字。是不是应该让他去搜索markdown转成html再去掉html标签后的纯文字更好呢,应该怎么操作呢。。

追梦人物 [博主] mozhemeng
可以在 model 添加一个新的字段存储 html 原文,然后让搜索殷勤索引这个字段并且对这个字段的内容进行搜索即可。

知而不倦
博主,搜索的结果前面的文字会被省略号代替,这个是什么原因的,能让它显示不

追梦人物 [博主] 知而不倦
这个问题由于涉及到一些对源码的阅读和拓展,所以没有在教程中给出了,自己尝试通过 google 解决吧。

hldgaoshuo
博主,我的环境是python2.7,在最后一步建立索引文件时报错,ImportError: No module named commentshaystack。baidu和google都没有关于commentshaystack的信息,实在纠结。

追梦人物 [博主] hldgaoshuo
commentshaystack 是什么?看看是不是哪里导包是写错了?

cashlu hldgaoshuo

settings.py里面,installed_apps里面,comments后面少了一个逗号


chenzhixiang1992
您好,我的博客文章模型是Article,但是我建立搜索引擎索引文件的时候写成了templates/search/indexes/blog/article_text.txt,导致搜索不出来任何东西,请问有什么办法解决吗?另外把引擎索引改成Article_text.txt之后还是一样搜索不出任何东西

追梦人物 [博主] chenzhixiang1992
首先看一下索引文件有没有建立,还有就是 article_text.txt 中填写的需要索引的字段是否和 Article 模型中的字段匹配?

chenzhixiang1992 追梦人物 [博主]
您好,谢谢,这个问题已经解决,是前端模板引用数据的问题!

icaros217
所有代码部署完后,启动fabfile,出现错误:imporError:no module named haystack

追梦人物 [博主] icaros217
在 requirements.txt 中加入了依赖么?

yeexin 追梦人物 [博主]

同上问题,requirementx.txt中已有依赖,前面是使用pip freeze>requirements.txt生成的,但是运行python manage.py rebuild_index依然提示ModuleNotFoundError,求解


追梦人物 [博主] yeexin

怀疑是版本问题,很久没有用这个库了,对此一无所知。


科兴一把刀
有个问题,比如我有一篇文章,标题是77,内容是7777,在搜索的时候,只有搜索77或者7777(完全匹配标题或内容)才能搜索出文章,搜索7,777就搜不出,这个是要怎么处理呢?

科兴一把刀 科兴一把刀
代码我是全部复制下来的,应该不会有错

追梦人物 [博主] 科兴一把刀
这是分词的问题,jieba 默认分词不是很强,可能它把 77777 当做一个词。个人推荐不必过分纠结于不常用的搜索关键词。实现一个完善的,考虑各种边界条件和各个用户搜索习惯的搜索引擎是一个极为复杂的问题。

科兴一把刀 追梦人物 [博主]
嗯,原来如此,我还以为是我代码有问题。 谢谢博主的系列好文!

ResidualC
博主是否考虑增加一个返回顶部按钮的功能

追梦人物 [博主] ResidualC
这是纯粹的 js 功能,不妨自己实现。

sakura1357
配置blogproject/settings.py时,path 应该是PATH,必须大写才行,要不然build index时会报错。

jennei
那个 query变量是怎么来的,我的是空

追梦人物 [博主] jennei
query 是 search 视图函数自动获取的。即从搜索表单的 name=q 的 input 控件提取的值。

jennei 追梦人物 [博主]
嗯,之前我写的查询参数名字不叫q导致出现了问题,后来改回q后就正常了

All-Nil 追梦人物 [博主]
博主,请问为什么搜索表单的 input 控件必须 name=q 呢,我也是改成q后,query的值才不为空了,没有找到哪地方用'q'进行获取的代码

追梦人物 [博主] All-Nil
Haystack 的 searchview 视图中有对 q 的处理,可以去看看就明白了。

Oak_Suen_Germany
博主,请问为什么,我修改css文件,网站的显示效果还是不变呢

Oak_Suen_Germany Oak_Suen_Germany
问题解决了,我用的bootstrap把之前的css文件覆盖了

Oak_Suen_Germany
感谢博主哈,从头到尾学完了,有机会可以讲下怎么添加分享文章到社交软件的功能吗

追梦人物 [博主] Oak_Suen_Germany
这个非常简单的,你可以搜搜 jiathis

Oak_Suen_Germany
AttributeError: 'function' object has no attribute 'has_morph'
建立索引文件时 发生上面这个错误。
还有就是高亮感觉不是很清楚,
{% highlight result.summary with query %} 这个应该放在哪里呢

Oak_Suen_Germany Oak_Suen_Germany
问题解决了呢,自己疏忽了

mihelloO
等搞定allauth就研究下。

mihelloO mihelloO
还是先搞定回复跳转next问题先。

Ehco
关于高亮的部分,感觉有点混乱,
请问是直接在result.htm模板里加入{% load highlight %}并且添加css文件
就能自动高亮了么?

追梦人物 [博主] Ehco
是的,然后对你需要高亮的内容使用 highlight 模板标签即可,具体用法见正文。