记一次django_haystack的坑

使用的是 whoosh 和jieba :
pip install whoosh
pip install jieba
首先在django,导入我们的haystack的应用

INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','index','ranking','user','play','search','comment','captcha',#验证码'haystack',#搜锁引擎
]

haystack 配置,在setting中加入如下配置:

#配置haystack
HAYSTACK_CONNECTIONS = {'default': {# 这里配置搜索引擎 路劲为:项目应用名+whoosh_cn_backend+WhooshEngine'ENGINE': 'search.whoosh_cn_backen.WhooshEngine',#后面rebuild_index,生成的索引文件目录'PATH': os.path.join(BASE_DIR, 'whoosh_index'),'INCLUDE_SPELLING': True,},
}
#设置分页显示的数据量
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 4
#当数据库改变是,自动更新索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'

我们搜索应用是search,所以在search路径下,需要创建两个haystack需要文件,search_indexes.py 和whoosh_cn_backend.py

search_indexes.py 代码如下:

from haystack import indexes
from index.models import Songclass ProductIndex(indexes.SearchIndex,indexes.Indexable):#,template_name='search/indexes/search/song_text.txt'text = indexes.CharField(document=True,use_template=True,template_name='search/indexes/search/song_text.txt')def get_model(self):#song可以改成实际的modelreturn Songdef index_queryset(self, using=None):return self.get_model().objects.all()

这主要是一个关联操作,定义我们的数据表的model的索引类
text 这个字段是必须的,document=True只能有一个,use_template =true 表示使用模板,这个模板的路径必须按照如下格式: templates/search/indexes/appname/model_text.txt ,如果不按照这个路径的话,就使用template_name 参数,指定模板文件;
第一个坑:当我们模板路径创建错误的时候,修正之后,重新rebuild_index 和update_index都不好使,会一直提示原来错误的模板不存在,这个坑纠结了我一个礼拜,最后,只能指定模板路径的方式,也就是template_name错误信息类似如下:

模板的内容如下:

{{ object.song_name }}
{{ object.song_singer }}
{{ object.song_album }}

模板的内容就是我们索引所在的表字段,haystack 在这三个字段上建立索引
第二个文件whoosh_cn_backend.py 这个文件可以从我们的haystack的backhend目录下复制,唯一需要修改的就是加入对中文的分词,因为这个默认是不支持中文的,找到下面这句话,按照如下修改下:

         from jieba.analyse import  ChineseAnalyzer#schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=StemmingAnalyzer(), field_boost=field_class.boost, sortable=True)#修改为jieba分词schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=ChineseAnalyzer(),field_boost=field_class.boost, sortable=True)

之后,通过python manage.py rebuild_index 命令,生成我们的索引文件:

在我们app的目录下,会生成上面这个目录,准备工作做好了之后,就是我们的view方法了,view 需要继承django.views 里的SearchView

from django.shortcuts import render,redirect
from index.models import *
# Create your views here.
from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger
from haystack.views import SearchView
from django.views import View
from music import settings
#搜索引擎 全站搜索
class MySearchIndex(SearchView):template = 'search.html'#我们通过重写extra_context 来定义我们自己的变量,#通过看源码,extra_context 默认返回的是空,然后再get_context方法里面,把extra_context#返回的内容加到我们self.context字典里def extra_context(self):context = super(MySearchIndex,self).extra_context()search_song = Dynamic.objects.select_related('song').order_by('-dynamic_search').all()[:6]context['search_song']= search_songreturn contextdef create_response(self):if not self.request.GET.get('q'):print(self.request.GET.get('q'))search_song = Dynamic.objects.select_related('song').order_by('-dynamic_search').all()[:6]song_info = Song.objects.all()paginator = Paginator(song_info, settings.HAYSTACK_SEARCH_RESULTS_PER_PAGE)try:page = paginator.page(int(self.request.GET.get('page',1)))except PageNotAnInteger:page = paginator.page(1)except EmptyPage:page = paginator.page(paginator.num_pages)print(page)return render(self.request, self.template, locals())else:qs = super(MySearchIndex, self).create_response()# print(self.get_context())return qs

haystack 默认是有几个变量的,这几个变量存在context 的,最终前端接受的数据都在context字典里,所以如果我们定义自己的变量的话,也需要加载context里:
我们可以通过打印的方式看一下:print(self.get_context):

'query': '三国恋', 'form': <ModelSearchForm bound=True, valid=True, fields=(q;models)>, 'page': <Page 1 of 1>, 'paginator': <django.core.paginator.Paginator object at 0x0000020A5659CB38>, 'suggestion': None, '

query 是我们搜索的关键字,form 一般不用,我们可以自己用表单的get提交方式模拟,但是表单的id必须是q,fields 没太搞明白是干啥的,page 和 paginator 就是djang默认分页相关的两个变量
create_response 方法就是自定义我们的响应体了,看下前端的代码就知道为什么这么写了,

{% extends "title_base.html" %}
{% block title  %}
{% load staticfiles %}{% load highlight %}
<link type="image/x-icon" rel="shortcut icon" href="{% static "favicon.ico" %}">
<link type="text/css" rel="stylesheet" href="{% static "css/common.css" %}">
<link type="text/css" rel="stylesheet" href="{% static "css/search.css" %}"></head>
<body><div class="header"><a href="/" class="logo" title="首页"><img alt="我的音乐" src="{% static "image/logo.png" %}"></a><div class="search-box"><form id="searchForm" action="" method="get" target="_blank"><!-- 模拟表单提交 --><div class="search-keyword"><input id="q" name="q" type="text" class="kword" maxlength="120" placeholder="音乐节"  /></div><input id="subSerch" type="submit" class="search-button" value="搜 索" /></form><div id="suggest" class="search-suggest"></div><div class="search-hot-words">{% for song in search_song  %}<a target="play" href="{% url 'play' song.song.song_id %}" >{{ song.song.song_name }}</a>{% endfor  %}</div></div></div><!--end header--><div class="nav-box"><div class="nav-box-inner"><ul class="nav clearfix"><li><a href="/">首页</a></li><li><a href="{% url 'ranking' %}" target="_blank">歌曲排行</a></li><li><a href="{% url 'home' 1 %}" target="_blank">用户中心</a></li></ul></div></div><!--end nav-box--><!--wrapper--><div class="wrapper clearfix" id="wrapper"><div class="mod_songlist"><ul class="songlist__header"><li class="songlist__header_name">歌曲</li><li class="songlist__header_author">歌手</li><li class="songlist__header_time">时长</li><li class="songlist__header_album">专辑</li></ul><ul class="songlist__list">{%for list in page.object_list %}<li class="js_songlist__child"><div class="songlist__item"><div class="songlist__songname"><span class="songlist__songname_txt"><!-- 通过query 判断是haystack 的响应内容,还是我们自己的响应内容 --><!-- 注意haystack 响应和我们自己查询的数据的区别,这也是我的第二个坑了:list.object.song_name  和 list.song_name  -->{% if query %}<a href="{% url 'play' list.object.song_id %}" class="js_song" target="play" >{% highlight list.object.song_name with query %}</a>{% else %}<a href="{% url 'play' list.song_id %}" class="js_song" target="play" >{{ list.song_name }}</a>{% endif %}</span></div><div class="songlist__artist">{% if query %}<a href="javascript:;" class="singer_name" >{% highlight list.object.song_singer with query %}</a>{% else %}<a href="javascript:;" class="singer_name" >{{ list.song_singer }}</a>{% endif %}</div><div class="songlist__time">{% if query %}{{list.object.song_time}}{% else %}{{ list.song_time }}{% endif %}</div><div class="songlist__album">{% if query %}<a href="javascript:;" class="singer_album" >{% highlight list.object.song_album with query %}</a>{% else %}<a href="javascript:;" class="singer_album" >{{ list.song_album }}</a>{% endif %}</div></div></li>{%endfor %}</ul><div class="page-box"><div class="pagebar" id="pageBar">{% if page.has_previous %}{% if query %}<a href="{% url 'search' %}?page={{ page.previous_page_number }}&amp;?q={{ query }}" class="prev" target="_self"><i></i>上一页</a>{% else %}<a href="{% url 'search' %}?page={{ page.previous_page_number }}" class="prev" target="_self"><i></i>上一页</a>{% endif %}{% endif %}{% for item in page.paginator.page_range %}{% if page.number == item %}<span class="sel">{{ item }}</span>{% else %}{% if query %}<a href="{% url 'search' %}?page={{ item }}&amp;?q={{ query }}" target="_self">{{ item }}</a>{% else %}<a href="{% url 'search' %}?page={{ item }}" target="_self">{{ item }}</a>{% endif %}{% endif %}{% endfor %}{% if page.has_next %}{% if query %}<a href="{% url 'search' %}?page={{ page.next_page_number }}&amp;?q={{ query }}" class="next" target="_self">下一页<i></i></a>{% else %}<a href="{% url 'search' %}?page={{ page.next_page_number }}" class="next" target="_self">下一页<i></i></a>{% endif %}{% endif %}</div></div></div><!--end mod_songlist--></div><!--end wrapper--><!--footer-->{% endblock  %}

第二个坑:haystack page 对象里的queryset 的格式我们一般数据库查询出来的queryset 访问是有区别的,前者是需要通过object 对象获取具体的值,list.object.song_album,而后者,直接list.song_album 就可以获取到结果
最后就是配置url了:

from django.urls import path
from . import views
urlpatterns = [#path('<int:page>.html', views.searchView, name='search'),#因为我们SearchView 默认是有__call__方法的,所以可以直接通过类名调用path('search.html', views.MySearchIndex(), name='search'),
]

记录下,django_haystack 实际使用经验和我自己遇到的两个大坑。在实际的排查的时候,大家可以通过打印我们的haystack context 来分析是haystack的问题还是我们自己代码的问题。haystack 的中文文档不是很全,网上的一些教程也都是抄来抄去,而且很基础,自己最后只能去看源码,虽然也没看懂,但是还是了解一个大概,不至于两眼一抹黑
,大家也可以去看看,对分析问题还是有些帮助的

django haystack一次使用总结相关推荐

  1. Diango博客--22.Django Haystack 全文检索与关键词高亮

    文章目录 1. Django Haystack 简介 2. 安装 django-haystack和elasticsearch 2 3. 构建容器来运行 elasticsearch 服务 4. 配置 H ...

  2. Django开发个人博客网站——19、通过Django Haystack实现搜索功能(上)

    该博客最开始采用的模板是并不包括搜索功能的,在主页只有主页.归档和分类三个部分.最后博主自己添加了搜索框,不过其实不太想让大家使用这个功能,因此将搜索框隐藏了,只有再点击搜索时,才会显现出来.但是这个 ...

  3. django+haystack+elasticsearch优化查询效率

    django+haystack+elasticsearch优化查询效率 背景 安装环境 配置 1.在settings中的配置 2.在子应用下创建索引文件 3.指定索引模板文件 4.使用命令创建索引 索 ...

  4. Django+haystack+jieba进行全文检索

    最近,在做一个全文检索的功能,找了两个方案: mysql的全文检索索引 优点:配置起来简单,改mysql配置即可 缺点:无法在django使用模型生成,查询语句也无法使用orm,只能用原生sql 基于 ...

  5. django+haystack+ElasticsearchSearch

    django安装再次不介绍了 Elasticsearch参考该博主 先装docker,再一键安装docker pull elasticsearch:2.4.4 在此记录几个docker命令 docke ...

  6. Django博客搭建-新闻模块6-新闻搜索功能(Django+Haystack+elasticsearch)

    Blog项目--新闻模块 文章目录 Blog项目--新闻模块 一.需求分析 二.搜索引擎原理 三.Elasticsearch 特点 四.使用docker安装elasticsearch 五.后端代码实现 ...

  7. django搜索 关键字 全文检索haystack 搜索分词数据库

    Django Haystack 简介 django-haystack 是一个专门提供搜索功能的 django 第三方应用,它支持 Solr.Elasticsearch.Whoosh.Xapian 等多 ...

  8. python django web典型模块开发实战下载_Django实战 Python Web典型模块与项目开发

    本书结合样例,介绍 Django 的基础知识.主要模块的开发以及权限管理等高级内容,并且通过图书管理系统.博客系统.车费管理系统 3 个项目的开发实战,使读者既能掌握 Django 的重要开发技术,又 ...

  9. 搜索关键字高亮_Django Haystack 全文检索与关键词高亮

    作者:HelloGitHub-追梦人物[1] 文中所涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库[2] 点击本文最下方的"阅读原文"即可获取 博客提供 RS ...

最新文章

  1. Centos 7 技巧
  2. 优化 最长上升子序列_LIS - 最长上升子序列 (二分优化)
  3. 第1步 新建spring+springmvc+mybatis项目 每步都有 讲解 巨详细
  4. 训练集的识别率一直波动_机器学习验证集为什么不再有新意?
  5. Matlab常见问题处理——错误使用 xlswrite (line 219),调用错误,调度异常: 参数错误。
  6. 东方通没有创造中间件 却在定义中间件的“化蝶”
  7. applet java_在浏览器中运行java applet
  8. 信号ctft频谱matlab,信号、系统分析与控制(MATLAB版)第4章连续信号的频域分析.ppt...
  9. eric python mysql_joson 、python和mysql的使用
  10. access查找出生日期年份_access怎样利用出生日期计算年龄呀!
  11. 目标检测学习笔记——使用wandb
  12. win7保护眼睛的颜色设置方法
  13. 一张表左关联另外两张表,三表关联
  14. 备份android分区,安卓手机手动【备份+还原】分区
  15. centos8.2+Tesla T4搭建深度学习运行环境
  16. 云呐|医院医疗的IT设备信息化资产盘点管理系统
  17. 【opencv四】利用opencv读取显示视频
  18. 个人博客系统---基本功能的实现
  19. 获取商品ID下所有的sku精准库存api
  20. java将汉字转成拼音首字母大写字母_java实现将汉字转为首字母、拼音

热门文章

  1. ElementUI从PNG开始,自己添加ICON
  2. iphone电压测试软件,新款iPhone SE充电兼容性大测试之45W篇
  3. Ubuntu18.04 安装QQ、Tim、微信与win无差异
  4. JavaScript localStorage、this、let、const
  5. 基层管理者的角色定位
  6. iis和tomcat5整合
  7. Js 跟手转动的罗盘指针
  8. Windows11、10,安装最新版ENSP和最新版HCL模拟器教程、无脑下一步!带下载链接
  9. 生命早期肠道微生物组和疫苗功效
  10. 养肾=养命!这7个最伤肾的行为你犯了吗?程序员收藏