實現用戶在頁面可自由搜索某個商品的功能。
第1步:準備搜索功能用到的庫
pip install whoosh
pip install jieba
pip install django-haystack
- whoosh是搜索引擎,對英文支持較好,但對中文效果不佳。
- jieba為中文分詞庫,彌補whoosh的缺陷。
- django-haystack為在django項目中使用搜索引擎的工具應用,通過它可以在不修改代碼的情況下使用不同的搜索引擎。
第2步:在settings.py中添加haystack應用
INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','areas','carts','contents','goods','users','orders','payment','verifications','haystack'
]
第3步:在settings.py中新境搜索引擎whoosh的配置項
HAYSTACK_CONNECTIONS = {'default': {# 引擎使用whoosh'ENGINE': 'haystack.backends.whoosh_cn_backend.WhooshEngine',# 索引文件路徑'PATH': os.path.join(BASE_DIR, 'whoosh_index')}
}
# 添加、修改、刪除數據時,自動生成索引
HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
第4步:將Whoosh自帶的分詞組件替換為jieba
在虛擬環境下(.venv\Lib\site-packages\haystack)創建ChineseAnalyzer.py
import jiebafrom whoosh.analysis import Tokenizer, Tokenclass ChineseTokenizer(Tokenizer):"""在 Whoosh 搜索引擎中, Token 對象是分詞過程中的核心數據結構,主要作用包括:1. 存儲分詞信息 :- text : 分詞后的實際文本內容- original : 原始分詞文本(可能與處理后的不同)- boost : 權重值,影響搜索結果排序2. 記錄位置信息 :- pos : 詞在文本中的位置序號- startchar / endchar : 字符級別的起始和結束位置3. 控制索引行為 :- removestops : 是否移除停用詞- mode : 控制索引模式(如存儲位置信息等)"""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 = wt.boost = 1.0if 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 tdef ChineseAnalyzer():return ChineseTokenizer()
復制/haystack/backends下的whoosh_backend.py文件,將副本更名為whoosh_cn_backend.py
打開whoosh_cn_backend.py,引入中文分析器文件ChineseAnalyzer.py
將analyzer=field_class.analyzer or StemmingAnalyzer(),
替換為analyzer = ChineseAnalyzer(),
在goods應用下創建索引類search_indexes.py,代碼如下
from haystack import indexesfrom .models import SKUclass SKUIndex(indexes.SearchIndex, indexes.Indexable):"""索引數據模型類"""# 接收索引字段:使用文檔定義索引字段,并且使用模板語法渲染# document=True表示該字段是主要進行關鍵字查詢的字段,use_template=True表明后續要通過一個數據模板指明需要檢索的字段text = indexes.CharField(document=True, use_template=True)def get_model(self):"""返回建立索引的模型類"""return SKUdef index_queryset(self, using=None):"""返回要建立索引的數據查詢集"""return self.get_model().objects.filter(is_launched=True)
在templates/search/indexes/目錄下創建goods目錄,在其中創建sku_text.txt,在其中指定索引的屬性。
{{object.id}}
{{object.name}}
{{object.caption}}
執行下面命令,手動生成初始索引
python .\manage.py rebuild_indexAre you sure you wish to continue? [y/N] y
在項目urls.py中增加haystack路由配置項
path('search/', include('haystack.urls')),
在templates/search/目錄下新增搜索結果模板search.html
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"><title>小魚商城-商品搜索</title><link rel="stylesheet" type="text/css" href="{{ static('css/jquery.pagination.css') }}"><link rel="stylesheet" type="text/css" href="{{ static('css/reset.css') }}"><link rel="stylesheet" type="text/css" href="{{ static('css/main.css') }}"><script type="text/javascript" src="{{ static('js/jquery-1.12.4.min.js') }}"></script><script type="text/javascript" src="{{ static('js/vue-2.5.16.js') }}"></script><script type="text/javascript" src="{{ static('js/axios-0.18.0.min.js') }}"></script>
</head>
<body>
<div id="app"><div class="header_con"><div class="header" v-cloak><div class="welcome fl">歡迎來到小魚商城!</div><div class="fr"><div v-if="username" class="login_btn fl">歡迎您:<em>[[ username ]]</em><span>|</span><a href="{{ url('users:logout') }}">退出</a></div><div v-else class="login_btn fl"><a href="{{ url('users:login') }}">登錄</a><span>|</span><a href="{{ url('users:register') }}">注冊</a></div><div class="user_link fl"><span>|</span><a href="{{ url('users:info') }}">用戶中心</a><span>|</span>{# <a href="{{ url('carts:info') }}">我的購物車</a>#}<span>|</span>{# <a href="{{ url('users:myorderinfo',args=(1,)) }}">我的訂單</a>#}</div></div></div></div><div class="search_bar clearfix"><a href="{{ url('contents:index') }}" class="logo fl"><img src="{{ static('images/logo.png') }}"></a><div class="search_wrap fl"><form method="get" action="/search/" class="search_con"><input type="text" class="input_text fl" name="q" placeholder="搜索商品"><input type="submit" class="input_btn fr" name="" value="搜索"></form><ul class="search_suggest fl"><li><a href="#">索尼微單</a></li><li><a href="#">優惠15元</a></li><li><a href="#">美妝個護</a></li><li><a href="#">買2免1</a></li></ul></div></div><div class="main_wrap clearfix"><div class="clearfix"><ul class="goods_type_list clearfix">{% for result in page %}<li><a href="detail.html"><img src="/static/images/goods/{{ result.object.default_image.url }}.jpg"></a><h4><a href="detail.html">{{ result.object.name }}</a></h4><div class="operate"><span class="price">¥{{ result.object.price }}</span><span>{{ result.object.comments }}評價</span><!-- <span class="unit">{{ result.object.sales }}臺</span>--><a href="#" class="add_goods" title="加入購物車"></a></div></li>{% else %}<p>沒有找到您要查詢的商品。</p>{% endfor %}</ul><div class="pagenation"><div id="pagination" class="page"></div></div></div></div><div class="footer"><div class="foot_link"><a href="#">關于我們</a><span>|</span><a href="#">聯系我們</a><span>|</span><a href="#">招聘人才</a><span>|</span><a href="#">友情鏈接</a></div><p>CopyRight ? 2024 北京小魚商業股份有限公司 All Rights Reserved</p><p>電話:010-****888 京ICP備*******8號</p></div>
</div>
<script type="text/javascript" src="{{ static('js/common.js') }}"></script>
<script type="text/javascript" src="{{ static('js/search.js') }}"></script>
<script type="text/javascript" src="{{ static('js/jquery.pagination.min.js') }}"></script>
<script type="text/javascript">$(function () {$('#pagination').pagination({currentPage: {{ page.number }},totalPage: {{ paginator.num_pages }},callback: function (current) {window.location.href = '/search/?q={{ query }}&page=' + current;}})});
</script>
</body>
</html>
在settings.py中增加HAYSTACK_SEARCH_RESULT_PER_PAGE控制結果頁面顯示的搜索記錄數量。
HAYSTACK_SEARCH_RESULTS_PER_PAGE = 5