pip install Django-haystack
pip install whoosh
pip install jieba
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'haystack',
'apps.search', # 全局搜索模块
]
# 配置HayStack
HAYSTACK_CONNECTIONS = {
'default': {
# 设置搜索引擎,文件是apps下的serach的whoosh_cn_backend.py
# 如果search模块未在apps下请自行替换或者去掉apps
'ENGINE': 'apps.search.whoosh_cn_backend.WhooshEngine',
'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
'INCLUDE_SPELLING': True,
},
}
# 设置每页显示的数据量
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 2
# 当数据库改变时,自动更新索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
# 顶部添加 引入jieba分词器模块
from jieba.analyse import ChineseAnalyzer
schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=StemmingAnalyzer (), field_boost=field_class.boost, sortable=True)
schema_fields[field_class.index_fieldname] = TEXT(stored=True, analyzer=ChineseAnalyzer(), field_boost=field_class.boost, sortable=True)
from django.db import models
class Poetry(models.Model):
id = models.AutoField('序号', primary_key=True)
name = models.CharField('名称', max_length=50)
author = models.CharField('作者', max_length=20)
detail = models.CharField('内容', max_length=300)
# 设置返回值
def __str__(self):
return self.name
# 本文件名称不允许修改,否则将无法创建索引
from haystack import indexes
from apps.search.models import Poetry
# 类名必须为模型名+Index,比如模型Poetry,则索引类为PoetryIndex
# 其对应的索引模版路径应为/项目的应用模块名称/templates/search/indexes/项目的应用模块名称/模型(小写)_text.txt
class PoetryIndex(indexes.SearchIndex, indexes.Indexable):
# doucument=True代表搜索引擎将使用此字段的内容作为索引进行检索
# use_template=True代表使用索引模版建立索引文件
text = indexes.CharField(document=True, use_template=True)
# 将索引类与模型Poetry进行绑定
def get_model(self):
return Poetry
# 设置索引的查询范围
def index_queryset(self, using=None):
return self.get_model().objects.all()
# templates/search/indexes/search/poetry_text.txt
{{ object.name }}
{{ object.author }}
{{ object.detail }}
from django.urls import path
from . import views
urlpatterns = [
# 搜索引擎,上一层路由为search
path('find/', views.MySearchView(), name='haystack'),
]
from django.shortcuts import render
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.conf import settings
from .models import *
from haystack.views import SearchView
# 视图以通用视图实现
class MySearchView(SearchView):
# 模版文件
template = 'search.html'
# 重写响应方式,如果请求参数q为空,返回模型Poetry的全部数据,否则根据参数q搜索相关数据
def create_response(self):
if not self.request.GET.get('q', ''):
show_all = True
poetry = Poetry.objects.all()
paginator = Paginator(poetry, settings.HAYSTACK_SEARCH_RESULTS_PER_PAGE)
try:
page = paginator.page(int(self.request.GET.get('page', 1)))
except PageNotAnInteger:
# 如果参数page的数据类型不是整型,则返回第一页数据
page = paginator.page(1)
except EmptyPage:
# 用户访问的页数大于实际页数,则返回最后一页的数据
page = paginator.page(paginator.num_pages)
return render(self.request, self.template, locals())
else:
show_all = False
qs = super(MySearchView, self).create_response()
return qs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>搜索引擎</title>
{# 导入CSS样式文件 #}
{% load staticfiles %}
<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">
<div class="search-box">
<form id="searchForm" action="" method="get">
<div class="search-keyword">
{# 搜索输入文本框必须命名为q #}
<input id="q" name="q" type="text" class="keyword" maxlength="120"/>
</div>
<input id="subSerch" type="submit" class="search-button" value="搜 索" />
</form>
<div id="suggest" class="search-suggest"></div>
</div>
</div>
<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_album">内容</li>
</ul>
<ul class="songlist__list">
{# 列出当前分页所对应的数据内容 #}
{% if show_all %}
{% for item in page.object_list %}
<li class="js_songlist__child" mid="1425301" ix="6">
<div class="songlist__item">
<div class="songlist__songname">{{ item.name }}</div>
<div class="songlist__artist">{{item.author}}</div>
<div class="songlist__album">{{ item.detail }}</div>
</div>
</li>
{% endfor %}
{% else %}
{# 导入自带高亮功能 #}
{% load highlight %}
{% for item in page.object_list %}
<li class="js_songlist__child" mid="1425301" ix="6">
<div class="songlist__item">
<div class="songlist__songname">{% highlight item.object.name with query %}</div>
<div class="songlist__artist">{% highlight item.object.author with query %}</div>
<div class="songlist__album">{% highlight item.object.detail with query %}</div>
</div>
</li>
{% endfor %}
{% endif %}
</ul>
{# 分页导航,如有疑问请参考本书分页功能 #}
<div class="page-box">
<div class="pagebar" id="pageBar">
{# 上一页的URL地址 #}
{% if page.has_previous %}
{% if query %}
<a href="{% url 'search:haystack'%}?q={{ query }}&page={{ page.previous_page_number }}" class="prev">上一页</a>
{% else %}
<a href="{% url 'search:haystack'%}?page={{ page.previous_page_number }}" class="prev">上一页</a>
{% endif %}
{% endif %}
{# 列出所有的URL地址 #}
{% for num in page.paginator.page_range %}
{% if num == page.number %}
<span class="sel">{{ page.number }}</span>
{% else %}
{% if query %}
<a href="{% url 'search:haystack' %}?q={{ query }}&page={{ num }}"
target="_self">{{num}}</a>
{% else %}
<a href="{% url 'search:haystack' %}?page={{ num }}" target="_self">{{num}}</a>
{% endif %}
{% endif %}
{% endfor %}
{# 下一页的URL地址 #}
{% if page.has_next %}
{% if query %}
<a href="{% url 'search:haystack' %}?q={{ query }}&page={{ page.next_page_number }}" class="next">下一页</a>
{% else %}
<a href="{% url 'search:haystack' %}?page={{ page.next_page_number }}" class="next">下一页</a>
{% endif %}
{% endif %}
</div>
</div>
</div>
</div>
</body>
</html>