本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习

一般搜索功能架构为:搜索框架+搜索引擎(包括分词方式)

这里搜索框架选择:

django-haystack:是django的开源搜索框架,该框架支持Solr,Elasticsearch,Whoosh, *Xapian*搜索引擎,不用更改代码,直接切换引擎,减少代码量。

搜索引擎使用:

Whoosh:这是一个由纯Python实现的全文搜索引擎,没有二进制文件等,比较小巧,配置比较简单,性能相对低一些,不过用于小网站足矣。

分词方式使用:

Jieba:由于Whoosh自带的是英文分词,对中文的分词支持不是太好,故用jieba替换whoosh的分词组件。

系统环境信息为:Centos7,Python 3.8.2,Django 3.0.3

djang-haystack

安装

pip install django-haystack

注意这里安装的是djang-haystack,而不是pip install haystack,我第一次安装时安装成了haystack,然后又再运行了 pip install django-haystack,这样启动项目后可能会导致冲突而报错"cannot import name 'connections' from 'haystack' ",解决方式就是,将haystack和django-haystack都卸载掉,然后重新安装django-haystack即可

安装完djang-haystack之后,启动项目又报了另外一个错:"cannot import name 'six' from 'django.utils",原因是django 3.x 系列删除了six.

解决方式是:

1. 安装six

pip install six

2. 进入报错的虚拟环境目录

cd /home/gong/.conda/envs/dailyfresh/lib/python3.8/site-packages/

将该目录下的six.py文件拷贝一份到该目录下的django/utils目录下

cp six.py django/utils

3. 修改虚拟环境的haystack目录下的inputs.py文件

vim /home/gong/.conda/envs/dailyfresh/lib/python3.8/site-packages/haystack/inputs.py
# 将
# from django.utils.encoding import force_text, python_2_unicode_compatible
# 改为
from django.utils.encoding import force_text
from django.utils.six import python_2_unicode_compatible

配置haystack

1. 修改setting.py

添加haystack应用

INSTALLED_APPS = [
...
'haystack',# 全文搜索框架
...
]

配置搜索引擎和索引文件

import os
HAYSTACK_CONNECTIONS = {
'default': {
'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
'PATH': os.path.join(BASE_DIR), 'whoosh_index'),
},
}

'ENGINE':搜索引擎使用的是虚拟环境中的haystack路径下的whoosh_backend.py文件中的WhooshEngine

'PATH':指的是生成的索引文件所在路径,即项目根目录下的whoosh_index文件夹路径,这个路径不需要手动创建,当运行生成索引文件命令时会自动创建

设置搜索结果页面每页显示的数量,默认为20个

HAYSTACK_SEARCH_RESULTS_PER_PAGE = 10

2. 索引文件的生成

注意下述路径和文件名都是固定的,其中其他都可以不用动,替换一下model的名字即可

在goods应用目录下新建一个search_indexes.py文件,在其中定义一个商品索引类。

from haystack import indexes
from goods.models import Goods class GoodsIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True) def get_model(self):
return Goods def index_queryset(self, using=None):
"""Used when the entire index for model is updated."""
return self.get_model().objects.all()

在templates下面创建文件templates/search/indexes/goods/good_text.txt

{{ object.name }}
{{ object.brief }}
{{ object.goodsspu.detail }}

生成索引文件:

python manage.py rebuild_index

3. 配置查询框和url

编辑查询框,注意method必须为get,action可以自定义表单提交路径,输入框的name必须为"q"

<div class="search_con fl">
<form method="get" action="{% url 'goods:search' %}">
<input type="text" class="input_text fl" name="q" placeholder="搜索商品">
<input type="submit" class="input_btn fr" name="" value="搜索">
</form>
</div>

编辑url,根据上面的action地址编辑对应的url,这里是编辑goods应用下的urls.py。

from django.urls import path
from .views import GoodsSearchView urlpatterns = [
...
# path('search/', include('haystack.urls')),
path('search/', GoodsSearchView.as_view(), name='search'),
...
]

注意这里有两种写法:

第一种为include('haystack.urls'),不自定义处理视图,直接使用haystack默认的context返回给模板文件,content内容为:

context = {
'query': self.query, # 搜索关键字
'form': self.form,
'page': page, # 当前页的page对象,遍历page对象,获取到的是SearchResult类的实例对象,对象的属性object才是模型类的对象。
'paginator': paginator, # 分页paginator对象
'suggestion': None,
}

第二种为自定义处理视图,GoodsSearchView.as_view(),可以新增自定义需要的数据信息给模板文件

class GoodsSearchView(SearchView):
'''商品搜索视图'''
def get_context_data(self, *args, **kwargs):
# 继承获取预定义的内容
context = super(GoodsSearchView, self).get_context_data(*args, **kwargs)
# 获取想要的数据库信息
# 获取全部商品种类
all_type = GoodsType.objects.all()
# 获取购物车数量
cart_count = get_cart_count(self.request)
# 添加上下文
context['all_type'] = all_type
context['cart_count'] = cart_count
context['page'] = context['page_obj']
print(context)
return context

这里注意新增了一个key为‘page’的属性,其值为预定义的key为‘page_obj’的值,原因是当我们使用上述第一种默认返回值时,page对象的key为‘page’,而第二种自定义视图中page对象的key为‘page_obj’

为了保持一致且一般情况我们都使用的key为‘page’代表page对象。

启动项目进行查询,发现页面报错:TemplateDoesNotExist,原因是haystack将查询结果展示在templates/search/search.html中,因此需要创建并编辑该文件

4. 编辑search.html

{{ query }}为查询条件,{{ page }}和{{ paginator }}对象与django的分页器对象一致,所有的属性和方法也一样。

注意这里的分页页码指向的地址,需要拼上?q={{查询关键字}}&amp;page={{页码}}

{% extends 'base_list.html'%}
{% block title %}天天生鲜-搜索结果{% endblock title%}
{% block detail%}
<div class="breadcrumb">
<a href="#">{{ query }}</a>
<span>></span>
<a href="#">搜索结果</a>
</div>
搜索字段:{{ query }}</br>
page对象:{{ page }}</br>
paginator对象:{{ paginator }}</br>
<div class="main_wrap clearfix">
<ul class="goods_type_list clearfix">
{% for result in page %}
<li>
result
<a href="{% url 'goods:detail' result.object.id %}"><img src="{{ result.object.image.url }}"></a>
<h4><a href="{% url 'goods:detail' result.object.id %}">{{ result.object.name }}</a></h4>
<div class="operate">
<span class="prize">¥{{ result.object.price }}</span>
<span class="unit">{{ result.object.price }}/{{ result.object.uom }}</span>
<a href="#" class="add_goods" title="加入购物车"></a>
</div>
</li>
{% empty %}
未搜索到结果
{% endfor %}
</ul> <div class="pagenation">
{% if page.has_previous %}
<a href="{% url 'goods:search' %}?q={{ query }}&amp;page={{ page.previous_page_number }}"><上一页</a>
{% endif %}
{% for num in paginator.page_range %}
<a href="{% url 'goods:search' %}?q={{ query }}&amp;page={{ num }}" {% if num == page.number %}class="active"{% endif %}>{{ num }}</a>
{% endfor %}
{% if page.has_next %}
<a href="{% url 'goods:search' %}?q={{ query }}&amp;page={{ page.next_page_number }}">下一页></a>
{% endif %}
</div>
</div>
{% endblock detail %}

jieba分词模块

由于原whoosh自带的分词方式对中文支持不是很好,于是使用对中文分词更好的jieba模块

安装jieba

pip install jieba

修改引擎文件

进入虚拟环境下的haystack/backends目录

cd /home/gong/.conda/envs/dailyfresh/lib/python3.8/site-packages/haystack/backends/

创建ChineseAnalyzer.py文件

import jieba
from whoosh.analysis import Tokenizer, Token class ChineseTokenizer(Tokenizer):
def __call__(self, value, positions=False, chars=False,
keeporiginal=False, removestops=True,
start_pos=0, start_char=0, mode='', **kwargs):
t = Token(positions, chars, removestops=removestops, mode=mode, **kwargs)
seglist = jieba.cut(value, cut_all=True)
for w in seglist:
t.original = t.text = w
t.boost = 1.0
if positions:
t.pos = start_pos + value.find(w)
if chars:
t.startchar = start_char + value.find(w)
t.endchar = start_char + value.find(w) + len(w)
yield t def ChineseAnalyzer():
return ChineseTokenizer()

新建复制whoosh_backend.py,命名为whoosh_cn_backend.py,编辑whoosh_cn_backend.py,引入中文分析类,内部采用jieba分词

cp whoosh_backend.py whoosh_cn_backend.py
from .ChineseAnalyzer import ChineseAnalyzer

...
# 查找
# analyzer=StemmingAnalyzer()
# 改为
analyzer=ChineseAnalyzer()

修改settings.py文件

将原whoosh_backend改成whoosh_cn_backend

# haystack+whoosh配置,全文检索框架
HAYSTACK_CONNECTIONS = {
'default': {
# 'ENGINE': 'haystack.backends.whoosh_backend.WhooshEngine',
'ENGINE': 'haystack.backends.whoosh_cn_backend.WhooshEngine',
'PATH': os.path.join(BASE_DIR, 'whoosh_index'),
},
}
# 设置搜索结果每页显示多少条数据
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 10

重新创建索引数据

python manage.py rebuild_index

DJANGO-天天生鲜项目从0到1-009-搜索功能实现(django-haystack+whoosh+jieba)的更多相关文章

  1. django天天生鲜项目

    .后台admin管理天天生鲜商品信息 models里 from django.db import modelsfrom tinymce.models import HTMLField #需要pip安装 ...

  2. DJANGO-天天生鲜项目从0到1-007-首页静态化与缓存

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

  3. python 天天生鲜项目

    python 天天生鲜项目 django版:https://github.com/Ivy-1996/fresh flask版:https://github.com/Ivy-1996/flask-fre ...

  4. Django学习---快速搭建搜索引擎(haystack + whoosh + jieba)

    Django下的搜索引擎(haystack + whoosh + jieba) 软件安装 haystack是django的开源搜索框架,该框架支持Solr,Elasticsearch,Whoosh, ...

  5. Django之天天生鲜项目

    准备工作 1.配置settings.py内置文件 注意: AUTH_USER_MODEL配置参数要在第一次迁移数据库之前配置,否则可能django的认证系统工作不正常 2.创建应用 3.配置主路由 一 ...

  6. DJANGO-天天生鲜项目从0到1-012-订单-用户订单页面

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

  7. DJANGO-天天生鲜项目从0到1-011-订单-订单提交和创建

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

  8. DJANGO-天天生鲜项目从0到1-010-购物车-购物车操作页面(勾选+删改)

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

  9. DJANGO-天天生鲜项目从0到1-009-购物车-Ajax实现添加至购物车功能

    本项目基于B站UP主‘神奇的老黄’的教学视频‘天天生鲜Django项目’,视频讲的非常好,推荐新手观看学习 https://www.bilibili.com/video/BV1vt41147K8?p= ...

随机推荐

  1. Python实用笔记 (5)使用dictionary和set

    dictionary 通过键值存储,具有极快的查找速度,但占用空间比list大很多 举个例子,假设要根据同学的名字查找对应的成绩,如果用list实现,需要两个list: names = ['Micha ...

  2. egret.sys.TextNode

    class Test extends egret.Shape{ protected textNode:egret.sys.TextNode; constructor(){ this.width = t ...

  3. DOM-BOM-EVENT(6)

    6.BOM 6.1.什么是BOM? BOM(Browse Object Model),浏览器对象模型,没有相关标准,是约定俗成的东西,定义了一些操作浏览器的方法和属性,大部分方法都是通过window对 ...

  4. Python 中的元类到底是什么?这篇恐怕是最清楚的了

    类作为对象 在理解元类之前,您需要掌握 Python 的类.Python 从 Smalltalk 语言中借用了一个非常特殊的类概念. 在大多数语言中,类只是描述如何产生对象的代码段.在 Python ...

  5. 对于python 作用域新的理解

    今天看Python习题,看到如下题目 def num(): return [lambda x: i*x for i in range(4)] print([m(2) for m in num()]) ...

  6. 洛谷 P3916 【图的遍历】

    这道题绿题有点高了吧... 我一开始的思路就是一个暴力的遍历,用递归加一个记忆化,对于一个点不断的往下搜索,然后确定最大的,返回,给上面的节点.就在这个过程中,我们是搜到最大的数然后返回给上层的数,那 ...

  7. css与javascript重难点,学前端,基础不好一切白费!

    JavaScript是一种属于网络的脚本语言,已经被广泛用于Web应用开发,常用来为网页添加各式各样的动态功能,为用户提供更流畅美观的浏览效果.通常JavaScript脚本是通过嵌入在HTML中来实现 ...

  8. Mybatis 报错

    Mybatis 报错 builder.BuilderException: Error parsing SQL Mapper Configuration Caused by: org.apache.ib ...

  9. HTML5(八)Web Workers

    HTML 5 Web Workers web worker 是运行在后台的 JavaScript,不会影响页面的性能. 什么是 Web Worker? 当在 HTML 页面中执行脚本时,页面的状态是不 ...

  10. [POJ3613] Cow Relays(Floyd+矩阵快速幂)

    解题报告 感觉这道题gyz大佬以前好像讲过一道差不多的?然鹅我这个蒟蒻发现矩阵快速幂已经全被我还给老师了...又恶补了一遍,真是恶臭啊. 题意 给定一个T(2 <= T <= 100)条边 ...