Django使用 haystack+whoosh实现搜索功能,并返回json数据

Django使用 haystack+whoosh实现搜索功能,并返回json数据

  1. 假设你已掌握了djangorestframework的基本用法

  2. 安装 haysyack, whoosh, jieba

#Ubuntu系统
sudo pip3 install django-haystack whoosh jieba
#windows
pip install django-haystack whoosh jieba -i https://pypi.tuna.tsinghua.edu.cn/simple/
  1. 配置haystack
#settings.py
INSTALLED_APPS = [
	...
	'haystack',
]

# 配置全文搜索

# 指定搜索引擎
HAYSTACK_CONNECTIONS = {  # 指定搜索引擎
    'default': {
        'ENGINE': 'prod.whoosh_cn_backend.WhooshEngine',  # whoosh_cn_backend 需自定义。
        'PATH': os.path.join(BASE_DIR, 'whoosh_index'),  # 索引文件存放的目录,建立索引时自动创建
    },
}

# 设置为每 10 项结果为一页,默认是 20 项为一页
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 10

# 当数据库改变时,自动更新索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
  1. 自定义搜索引擎:whoosh_cn_backend
# 在prod下创建whoosh_cn_backend.py
# 复制 site-packages\haystack\backends\whoosh_backend.py 中的内容,替换分词模块

# 在最上面导入 ChineseAnalyzer
from jieba.analyse import ChineseAnalyzer

# 搜索 StemmingAnalyzer 替换为 ChineseAnalyzer
  1. 对某app中的模型类建立全文索引(索引类)
#myapp>search_indexes.py   创建search_indexes.py文件(文件名不可以改)
from prod.models import GoodsModel  # 导入数据模型类
from haystack import indexes

# 创建一个索引类
class BookIndex(indexes.SearchIndex, indexes.Indexable):
    # 固定语句,惯例使用’text‘命名字段
    text = indexes.CharField(document=True, use_template=True)

    # document=True,说明搜索引擎使用该字段内容作为索引来检索,只能有一个字段具有该属性True
    # use_template=True 使用模板建立索引
    # 换名字的时候,注意配置HAYSTACK_DOCUMENT_FIELD = "XXX"

    def get_model(self):  # 必须
        return GoodsModel

    def index_queryset(self, using=None):
        """Used when the entire index for model is updated."""

        return self.get_model().objects.all()

  1. 创建模板文件
# 创建 templates/search/indexes/<yourapp>/<modelname>_text.txt 文件
# 写入如下内容:

{{ object.sku_name }}  # 必须object。后面为模型类要建立索引的字段
{{ object.title }}
{{ object.instruction }}

  1. 配置路由
from django.urls import path, re_path
urlpatterns = [
	...,
	re_path(r"search/$", views.SearchView.as_view()),
]
  1. 写视图类
# 任意views.py 文件

import json
from django.conf import settings
from django.core.paginator import InvalidPage, Paginator
from django.http import Http404, HttpResponse, JsonResponse
from haystack.forms import ModelSearchForm
from haystack.query import EmptySearchQuerySet

# 获取配置的每页数据。没有配置默认20
RESULTS_PER_PAGE = getattr(settings, 'HAYSTACK_SEARCH_RESULTS_PER_PAGE', 20)

class SearchView(APIView):
    # 必须为get方法
    def get(self, request, load_all=True, form_class=ModelSearchForm, searchqueryset=None, extra_context=None,
            results_per_page=None):
        query = ''
        results = EmptySearchQuerySet()
        if request.GET.get('q'):
            form = form_class(request.GET, searchqueryset=searchqueryset, load_all=load_all)

            if form.is_valid():
                query = form.cleaned_data['q']
                results = form.search()
        else:
            form = form_class(searchqueryset=searchqueryset, load_all=load_all)

        paginator = Paginator(results, results_per_page or RESULTS_PER_PAGE)
        try:
            p = int(request.GET.get('page', 1))
            page = paginator.page(p)
        except InvalidPage:
            return Response({
                "code": 404,
                "msg": "无搜索结果"
            })

        context = {
            'form': form,
            'page': page,
            'paginator': paginator,
            'query': query,
            'suggestion': None,
        }
        if results.query.backend.include_spelling:
            context['suggestion'] = form.get_suggestion()
        if extra_context:
            context.update(extra_context)

        return Response({
            "code": 200,
            "msg": "搜索成功",
            "data": [{
                "id": i.object.id,
                "sku_name": i.object.sku_name,
                "price": i.object.price,
                "selling_price": i.object.selling_price,
                "img": i.object.img,
                "title": i.object.title,
                "instruction": i.object.instruction,
                "count": i.object.count,
                "stock": i.object.stock,
                "online": i.object.online,
            } for i in page.object_list],
            "page": p,
            "count": paginator.count,
        })

  1. 建立索引文件
#模型类已存储数据的情况下
#每次更新索引相关内容都要重建索引,将数据同步到搜索引擎
python manage.py rebuild_index

#将数据库的数据---->同步到搜索引擎
#查询时,从搜索引擎 查询数据,比模糊查询更高效
  1. 访问路由
# http://127.0.0.1:8000/prod/search/?q=电视&page=1
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值