django项目搭建4商品搜索

商品的搜索

我们搜索的是商品信息,所以涉及goods层中的GoodsSKU表:

  • 使用全文检索来进行搜索功能的实现,haystack 是 django的开源搜索框架,该框架支持 SolrElasticsearchWhoosh*Xapian*搜索引擎,不用更改代码,直接切换引擎,减少代码量。
  • 搜索引擎使用 whoosh,这是一个由纯 Python 实现的全文搜索引擎,没有二进制文件等,比较小巧,配置比较简单,当然性能自然略低。
  • 中文分词 Jieba,由于 Whoosh 自带的是英文分词,对中文的分词支持不是太好,故用 jieba 替换 whoosh 的分词组件。

首先也就是最重要的要提一下,有些的命名必须是严格规定好的,不允许改变,下面会重要的提一下:

首先就是安装django-haystack,jieba,whoosh,然后进入haystack安装包下面的backends下面,

创建ChineseAnalyzer.py文件,在文件中写入下面代码,保存,看下面代码就知道,通过jieba来处理汉字的分词,然后返回出去:

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()

 

  1. 然后就是复制whoosh_backend.py文件,改为如下名称:whoosh_cn_backend.py,

打开复制出来的新文件whoosh_cn_backend.py,引入中文分析类,内部采用jieba分词。

from .ChineseAnalyzer import ChineseAnalyzer

更改词语分析类。

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

然后进入settings.py 配置haystack:

# 全文检索框架的配置
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'

首先进入我们的指定的应用下面创建一个文件:search_indexes.py,记住这个文件命名固定,同时写入以下内容,同时记住里面的类名称也是固定的:模型名称+Index, 函数名称都是固定的

from haystack import indexes
from goods.models import GoodsSKU

#指定某些类建立索引
class GoodsSKUIndex(indexes.SearchIndex,indexes.Indexable):
    #将索引文件创建好以后放在template下面的一个文件里面
    text=indexes.CharField(document=True,use_template=True)

    def get_model(self):
        #返回指定模型
        return GoodsSKU
     #建立索引数据
    def index_queryset(self, using=None):
        #返回所有模型数据
        return self.get_model().objects.all()

上面text中提到use_template,所以必须建立对应的模板文件,进入templates目录下,建立search/indexes/应用名称/商品表名称_text.txt,这些都是固定好的命名,同时在search目录下面建立search.html,如下截图效果:

Goodssku_text.txt 表示要按照什么来进行查询:

Search.html,表示点击搜索以后跳转的界面,对搜索商品进行展示,我们先看search_test.html,中的一些字段代表的名称,search.html是固定命名的,search_test.html是我们测试用的,这样命名,是无效的,只是为了我们测试用的,可以删了:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
{% load staticfiles %}
<head>
   <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
   <title>天天生鲜-商品搜索列表</title>
   <link rel="stylesheet" type="text/css" href="{% static 'css/reset.css'%}">
   <link rel="stylesheet" type="text/css" href="{% static 'css/main.css' %}">
</head>
<body>
   <div class="header_con">
      <div class="header">
         <div class="welcome fl">欢迎来到天天生鲜!</div>
         <div class="fr">
                {% if user.is_authenticated %}
                    <div class="login_info fl">
                        欢迎您:<em>{{ user.username }}</em>
                         <a href="{% url 'user:logout' %}">退出</a>
                    </div>
                {% else %}
                    <div class="login_btn fl">
                        <a href="{% url 'user:login' %}">登录</a>
                        <span>|</span>
                        <a href="{% url 'user:register' %}">注册</a>
                    </div>
                {% endif %}
            <div class="user_link fl">
               <span>|</span>
               <a href="{% url 'user:user' %}">用户中心</a>
               <span>|</span>
               <a href="cart.html">我的购物车</a>
               <span>|</span>
               <a href="{% url 'user:order' %}">我的订单</a>
            </div>
         </div>
      </div>    
   </div>

   <div class="search_bar clearfix">
      <a href="{% url 'goods:index' %}" class="logo fl"><img src="{% static 'images/logo.png' %}"></a>
      <div class="search_con fl">
            <form method="get" action="/search">
                <input type="text" class="input_text fl" name="q" placeholder="搜索商品">
                <input type="submit" class="input_btn fr" name="" value="搜索">
            </form>
      </div>
      <div class="guest_cart fr">
         <a href="#" class="cart_name fl">我的购物车</a>
         <div class="goods_count fl">{{ cart_count }}</div>
      </div>
   </div>

   <div class="navbar_con">
      <div class="navbar clearfix">
         <div class="subnav_con fl">
            <h1>全部商品分类</h1>    
            <span></span>        
            <ul class="subnav">
                    {% for type in types %}{# 显示所有分类 #}
                   <li><a href="{% url 'goods:list' type.id 1 %}" class="{{ type.logo }}">{{ type.name }}</a></li>
                    {% endfor %}
            </ul>
         </div>
         <ul class="navlist fl">
            <li><a href="{% url 'goods:index' %}">首页</a></li>
            <li class="interval">|</li>
            <li><a href="">手机生鲜</a></li>
            <li class="interval">|</li>
            <li><a href="">抽奖</a></li>
         </ul>
      </div>
   </div>

   <div class="breadcrumb">
      <a href="#">{{ query }}</a>
      <span>></span>
      <a href="#">搜索结果如下:</a>{# 当前种类 #}
   </div>

   <div class="main_wrap clearfix">

         <ul class="goods_type_list clearfix">
                {% for item in page %}{# 每一页商品的详细信息 #}
                    <li>
                        <a href="{% url 'goods:detail' item.object.id  %}"><img src="{{ item.object.image.url }}"></a>
                        <h4><a href="{% url 'goods:detail' item.object.id  %}">{{ item.object.name }}</a></h4>
                        <div class="operate">
                            <span class="prize">¥{{ item.object.price }}</span>
                            <span class="unit">{{ item.object.price }}/{{ item.object.unite }}</span>
                            <a href="#" class="add_goods" title="加入购物车"></a>
                        </div>
                    </li>
                {% endfor %}

         </ul>

         <div class="pagenation">{# 判断下一页显示 #}
                {% if page.has_previous %}
                <a href="/search?q={{ query }}&page={{ page.previous_page_number }}">上一页</a>
                {% endif %}
                {% for sku_page in paginator.page_range %}
                    {% if sku_page == skus_page.number %}
                       <a href="/search?q={{ query }}&page={{ sku_page }}" class="active">{{ sku_page }}</a>
                    {% else %}
                       <a href="/search?q={{ query }}&page={{ sku_page }}">{{ sku_page }}</a>
                    {% endif %}
                {% endfor %}
                {% if page.has_next %}
                <a href="/search?q={{ query }}&page={{ page.next_page_number }}">下一页></a>
                {% endif %}
         </div>
    </div>


然后就是我们首页的搜索,index.html中的搜索放在一个form表单中,action=”/search”是固定的,还有就是name=”q”也是固定的,详细如下:

<div class="search_con fl">
          <form method="get" action="/search">{# 全文检索框架 固定search q #}
              <input type="text" class="input_text fl" name="q" placeholder="搜索商品">
              <input type="submit" class="input_btn fr" name="" value="搜索">
          </form>
</div>

最后就是重建索引文件:

在终端中输入:python manage.py rebuild_index或者使用 update_index命令。

 

成功以后就是浏览器页面搜索展示:

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值