Django haystack实现全文搜索代码示例


Posted in Python onNovember 28, 2020

一、使用的工具

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

搜索引擎使用Whoosh,这是一个由纯Python实现的全文搜索引擎,没有二进制文件等,比较小巧,配置比较简单,当然性能自然略低。

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

其他:Python 3.4.4, Django 1.8.3,Debian 4.2.6_3

二、配置说明

现在假设我们的项目叫做Project,有一个myapp的app,简略的目录结构如下。

- Project
- Project
- settings.py
- blog
- models.py

此models.py的内容假设如下:

from django.db import models
from django.contrib.auth.models import User
class Note(models.Model):
  user = models.ForeignKey(User)
  pub_date = models.DateTimeField()
  title = models.CharField(max_length=200)
  body = models.TextField()

  def __str__(self):
    return self.title

1. 首先安装各工具

pipinstall whoosh django-haystack jieba

2. 添加 Haystack 到Django的INSTALLED_APPS

配置Django项目的settings.py里面的INSTALLED_APPS添加Haystack,例子:

INSTALLED_APPS = [ 
    'django.contrib.admin',
    'django.contrib.auth', 
    'django.contrib.contenttypes', 
    'django.contrib.sessions', 
    'django.contrib.sites', 

     # Added. haystack先添加,
     'haystack', 
     # Then your usual apps... 自己的app要写在haystakc后面
     'blog',
]

点我看英文原版

3. 修改 你的settings.py,以配置引擎

本教程使用的是Whoosh,故配置如下:

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

其中顾名思义,ENGINE为使用的引擎必须要有,如果引擎是Whoosh,则PATH必须要填写,其为Whoosh 索引文件的存放文件夹。

其他引擎的配置见官方文档

4.创建索引

如果你想针对某个app例如mainapp做全文检索,则必须在mainapp的目录下面建立search_indexes.py文件,文件名不能修改。内容如下:

import datetime
from haystack import indexes
from myapp.models import Note

class NoteIndex(indexes.SearchIndex, indexes.Indexable):
  text = indexes.CharField(document=True, use_template=True)
  
  author = indexes.CharField(model_attr='user')
  pub_date = indexes.DateTimeField(model_attr='pub_date')

  def get_model(self):
    return Note

  def index_queryset(self, using=None):
    """Used when the entire index for model is updated."""
    return self.get_model().objects.filter(pub_date__lte=datetime.datetime.now())

每个索引里面必须有且只能有一个字段为document=True,这代表haystack 和搜索引擎将使用此字段的内容作为索引进行检索(primary field)。其他的字段只是附属的属性,方便调用,并不作为检索数据。

注意:如果使用一个字段设置了document=True,则一般约定此字段名为text,这是在SearchIndex类里面一贯的命名,以防止后台混乱,当然名字你也可以随便改,不过不建议改。

并且,haystack提供了use_template=True在text字段,这样就允许我们使用数据模板去建立搜索引擎索引的文件,使用方便(官方推荐,当然还有其他复杂的建立索引文件的方式,目前我还不知道),数据模板的路径为yourapp/templates/search/indexes/yourapp/note_text.txt,例如本例子为blog/templates/search/indexes/blog/note_text.txt文件名必须为要索引的类名_text.txt,其内容为

{{ object.title }}
{{ object.user.get_full_name }}
{{ object.body }}

这个数据模板的作用是对Note.title,Note.user.get_full_name,Note.body这三个字段建立索引,当检索的时候会对这三个字段做全文检索匹配。

5.在URL配置中添加SearchView,并配置模板

在urls.py中配置如下url信息,当然url路由可以随意写。

(r'^search/', include('haystack.urls')),

其实haystack.urls的内容为,

from django.conf.urls import url
from haystack.views import SearchView

urlpatterns = [
  url(r'^$', SearchView(), name='haystack_search'),
]

SearchView()视图函数默认使用的html模板为当前app目录下,路径为myapp/templates/search/search.html
所以需要在blog/templates/search/下添加search.html文件,内容为

{% extends 'base.html' %}

{% block content %}
  <h2>Search</h2>

  <form method="get" action=".">
    <table>
      {{ form.as_table }}
      <tr>
        <td> </td>
        <td>
          <input type="submit" value="Search">
        </td>
      </tr>
    </table>

    {% if query %}
      <h3>Results</h3>

      {% for result in page.object_list %}
        <p>
          <a href="{{ result.object.get_absolute_url }}" rel="external nofollow" >{{ result.object.title }}</a>
        </p>
      {% empty %}
        <p>No results found.</p>
      {% endfor %}

      {% if page.has_previous or page.has_next %}
        <div>
          {% if page.has_previous %}<a href="?q={{ query }}&page={{ page.previous_page_number }}" rel="external nofollow" >{% endif %}« Previous{% if page.has_previous %}</a>{% endif %}
          |
          {% if page.has_next %}<a href="?q={{ query }}&page={{ page.next_page_number }}" rel="external nofollow" >{% endif %}Next »{% if page.has_next %}</a>{% endif %}
        </div>
      {% endif %}
    {% else %}
      {# Show some example queries to run, maybe query syntax, something else? #}
    {% endif %}
  </form>
{% endblock %}

很明显,它自带了分页。

6.最后一步,重建索引文件

使用python manage.py rebuild_index或者使用update_index命令。

好,下面运行项目,进入该url搜索一下试试吧。

三、下面要做的,使用jieba分词第一步

将文件whoosh_backend.py(该文件路径为python路径/lib/python3.4/site-packages/haystack/backends/whoosh_backend.py
)拷贝到app下面,并重命名为whoosh_cn_backend.py,例如blog/whoosh_cn_backend.py。修改如下
添加from jieba.analyse import ChineseAnalyzer
修改为如下

schema_fields[field_class.index_fieldname] =
TEXT(stored=True, analyzer=ChineseAnalyzer(),
field_boost=field_class.boost)

第二步

在settings.py中修改引擎,如下

import os
HAYSTACK_CONNECTIONS = {
  'default': {
    'ENGINE': 'blog.whoosh_cn_backend.WhooshEngine',
    'PATH': os.path.join(BASE_DIR, 'whoosh_index'
  },
}

第三步

重建索引,在进行搜索中文试试吧。

索引自动更新

如果没有索引自动更新,那么每当有新数据添加到数据库,就要手动执行update_index命令是不科学的。自动更新索引的最简单方法在settings.py添加一个信号。

 HAYSTACK_SIGNAL_PROCESSOR =
"haystack.signals.RealtimeSignalProcessor"

官方文档

看了这入门篇,你现在应该大概能配置一个简单的全文搜索了吧,如果想自定义怎么办? 建议阅读官方文档和github的源码。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
详解Python编程中包的概念与管理
Oct 16 Python
python处理html转义字符的方法详解
Jul 01 Python
python利用urllib实现爬取京东网站商品图片的爬虫实例
Aug 24 Python
pandas数据清洗,排序,索引设置,数据选取方法
May 18 Python
使用python判断你是青少年还是老年人
Nov 29 Python
Python函数返回不定数量的值方法
Jan 22 Python
Python操作配置文件ini的三种方法讲解
Feb 22 Python
python实现从本地摄像头和网络摄像头截取图片功能
Jul 11 Python
python 在右键菜单中加入复制目标文件的有效存放路径(单斜杠或者双反斜杠)
Apr 08 Python
pyinstaller打包单文件时--uac-admin选项不起作用怎么办
Apr 15 Python
python实现杨辉三角的几种方法代码实例
Mar 02 Python
Python first-order-model实现让照片动起来
Jun 25 Python
windows下python 3.9 Numpy scipy和matlabplot的安装教程详解
Nov 28 #Python
关于Python 解决Python3.9 pandas.read_excel(‘xxx.xlsx‘)报错的问题
Nov 28 #Python
Python self用法详解
Nov 28 #Python
Python3.9最新版下载与安装图文教程详解(Windows系统为例)
Nov 28 #Python
python安装sklearn模块的方法详解
Nov 28 #Python
Django-silk性能测试工具安装及使用解析
Nov 28 #Python
python 实现学生信息管理系统的示例
Nov 28 #Python
You might like
php编写的简单页面跳转功能实现代码
2013/11/27 PHP
关于js和php对url编码的处理方法
2014/03/04 PHP
使用PHP进行微信公众平台开发的示例
2015/08/21 PHP
thinkphp5 migrate数据库迁移工具
2018/02/20 PHP
javascript 按回车键相应按钮提交事件
2009/11/02 Javascript
简单的JavaScript互斥锁分享
2014/02/02 Javascript
node.js学习总结之调式代码的方法
2014/06/25 Javascript
详细解读AngularJS中的表单验证编程
2015/06/19 Javascript
JavaScript页面实时显示当前时间实例代码
2016/10/23 Javascript
js模仿微信朋友圈计算时间显示几天/几小时/几分钟/几秒之前
2017/04/27 Javascript
详解Vue.js搭建路由报错 router.map is not a function
2017/06/27 Javascript
微信小程序实现录音时的麦克风动画效果实例
2019/05/18 Javascript
vue登录注册实例详解
2019/09/14 Javascript
基于JavaScript的数据结构队列动画实现示例解析
2020/08/06 Javascript
Vue实现指令式动态追加小球动画组件的步骤
2020/12/18 Vue.js
[52:07]完美世界DOTA2联赛PWL S3 LBZS vs access 第二场 12.10
2020/12/13 DOTA
python3学习笔记之多进程分布式小例子
2018/02/13 Python
python实现从文件中读取数据并绘制成 x y 轴图形的方法
2018/10/14 Python
Python 常用模块 re 使用方法详解
2019/06/06 Python
关于pandas的离散化,面元划分详解
2019/11/22 Python
Python生成个性签名图片获取GUI过程解析
2019/12/16 Python
利用Tensorflow的队列多线程读取数据方式
2020/02/05 Python
numba提升python运行速度的实例方法
2021/01/25 Python
几个CSS3的flex弹性盒模型布局的简单例子演示
2016/05/12 HTML / CSS
请写出 float x 与"零值"比较的 if 语句
2016/01/04 面试题
高中学校对照检查材料
2014/08/31 职场文书
幼儿教师自我剖析材料
2014/09/29 职场文书
2014民事授权委托书范本
2014/09/29 职场文书
用人单位终止解除劳动合同证明书
2014/10/06 职场文书
群众路线表态发言材料
2014/10/17 职场文书
上课迟到检讨书范文
2015/05/06 职场文书
2015暑期社会实践个人总结
2015/07/13 职场文书
2015大学生暑期实习报告
2015/07/13 职场文书
学习经验交流会演讲稿
2015/11/02 职场文书
美德少年事迹材料(2016推荐版)
2016/02/25 职场文书
Android基础入门之dataBinding的简单使用教程
2022/06/21 Java/Android