基于Django的博客系统之用HayStack连接elasticsearch增加搜索功能(五)
上一篇:搭建基于Django的博客系统数据库迁移从Sqlite3到MySQL(四)
下一篇:基于Django的博客系统之增加类别导航栏(六)
功能概述
- 添加搜索框用于搜索博客。
需求详细描述
1. 添加搜索框用于搜索博客
- 描述: 在博客首页添加搜索框,用户可以通过关键词搜索博客文章。
- 功能要求:
- 搜索框位置:导航栏或页面顶部。
- 支持根据标题和内容进行搜索。
- 搜索结果显示匹配的博客列表。
- 用户故事:
- 作为用户,我希望能够通过搜索框快速找到感兴趣的博客文章。
技术结构
实现一个博客搜索功能,可以同时使用 Elasticsearch 和 MySQL 各自的优势。以下是如何区分和结合使用这两种技术的方法:
使用 MySQL 的部分
- 数据存储:
- 存储博客文章的基本信息,如标题、作者、发布时间、分类等。
- 存储用户信息、评论、标签等结构化数据。
- 基础查询和管理:
- 进行常规的 CRUD 操作,如创建、读取、更新、删除博客文章。
- 进行简单的过滤和排序,如按发布时间、作者、分类等查询文章。
使用 Elasticsearch 的部分
- 全文搜索:
- 存储和索引博客文章的全文内容,以支持全文搜索功能。
- 对用户搜索的关键词进行快速匹配,返回相关的文章列表。
- 复杂查询:
- 支持复杂的查询需求,如模糊搜索、布尔搜索、按相关性排序等。
- 支持自动补全、拼写纠错等高级搜索功能。
集成 MySQL 和 Elasticsearch
- 数据同步:
- 需要将 MySQL 中的博客文章数据同步到 Elasticsearch 中,以确保搜索功能能够使用最新的数据。
- 可以使用定时任务或实时数据同步机制来保持两者数据的一致性。例如,使用工具如 Logstash、Beats 或自定义的同步程序。
- 搜索接口设计:
- 提供一个统一的搜索接口,前端用户提交搜索请求时,后台从 Elasticsearch 中查询搜索结果。
- 查询到的搜索结果中包含文章的基本信息,从 Elasticsearch 返回文章的 ID,然后从 MySQL 中获取详细信息(如作者、评论等)。
实现步骤
要在 Django 博客应用中添加搜索框,以便用户可以搜索博客内容,可以按照以下步骤进行:
1. 安装 Django 搜索库
首先,确保你已经安装了 Django 搜索库。一个常用的选择是 django-haystack
库,它提供了与多个搜索引擎(如 Elasticsearch、Solr 和 Whoosh 等)集成的功能。
pip install django-haystack
2. 配置搜索引擎
选择并配置你想要使用的搜索引擎。例如,如果选择使用 Whoosh 搜索引擎,需要在 settings.py
文件中配置 Haystack 设置:
# settings.pyINSTALLED_APPS = [# 其他应用...'haystack',
]HAYSTACK_CONNECTIONS = {'default': {'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine','URL': 'http://localhost:9200/', # Elasticsearch 服务器的 URL'INDEX_NAME': 'haystack', # Elasticsearch 索引的名称},
}HAYSTACK_SIGNAL_PROCESSOR = 'haystack.signals.RealtimeSignalProcessor'
3. 创建搜索索引类
为你的博客模型创建一个搜索索引类,告诉 Haystack 如何索引你的数据。假设你有一个名为 Post
的博客模型:
# search_indexes.pyfrom haystack import indexes
from .models import Postclass PostIndex(indexes.SearchIndex, indexes.Indexable):text = indexes.CharField(document=True, use_template=True)def get_model(self):return Post
在这个示例中,我们使用 text
字段来索引博客内容。你可以根据需要添加更多的字段。
4. 创建搜索模板
在你的博客模板文件夹中创建一个模板文件,用于显示搜索结果。这个模板将根据搜索结果显示匹配的博客文章。
<!-- templates/search/post_text.txt -->{{ object.title }}
{{ object.content }}
同步索引:运行 Django 的管理命令来创建或更新搜索索引。
python manage.py rebuild_index
5. 更新 URL 配置
将搜索视图添加到你的 URL 配置中,以便用户可以访问搜索页面并执行搜索。
# urls.pyfrom django.urls import path
from . import viewsurlpatterns = [# 其他 URL 配置...path('search/', views.SearchView.as_view(), name='search'),
]
6. 创建搜索视图
创建一个视图类来处理搜索请求,并将搜索结果呈现给用户。
from haystack.query import SearchQuerySetdef search_view(request):query = request.GET.get('q', '')results = SearchQuerySet().filter(content=query)return render(request, 'search_results.html', {'results': results})
7. 创建搜索模板
创建一个模板文件,用于显示搜索结果。在这个模板中,你可以根据需要定制搜索结果的展示方式。
<!-- templates/search.html -->{% for result in page.object_list %}<h3><a href="{{ result.object.get_absolute_url }}">{{ result.object.title }}</a></h3><p>{{ result.object.content }}</p>
{% empty %}<p>No results found.</p>
{% endfor %}{% if is_paginated %}<div class="pagination"><span class="step-links">{% if page.has_previous %}<a href="?q={{ query }}&page=1">« first</a><a href="?q={{ query }}&page={{ page.previous_page_number }}">previous</a>{% endif %}<span class="current">Page {{ page.number }} of {{ page.paginator.num_pages }}.</span>{% if page.has_next %}<a href="?q={{ query }}&page={{ page.next_page_number }}">next</a><a href="?q={{ query }}&page={{ page.paginator.num_pages }}">last »</a>{% endif %}</span></div>
{% endif %}
8. 创建搜索表单
最后,创建一个搜索表单,让用户输入搜索关键字并提交搜索请求。
<!-- templates/search_form.html --><form action="{% url 'search' %}" method="get"><input type="text" name="q" placeholder="Search..."><button type="submit">Search</button>
</form>
将搜索表单包含在你的博客页面中的适当位置,用户就可以使用它来搜索博客内容了。
这就是在 Django 博客应用中添加搜索框的基本步骤。根据你的需求,你可以进一步定制搜索功能,例如添加搜索结果的高亮显示、自定义搜索表单字段等。
连接elasticsearch
具体参看这篇Windows安装ElasticSearch版本7.17.0
要连接 Elasticsearch,你需要配置 Django Haystack 的后端为 Elasticsearch 后端。下面是一些步骤:
- 安装 Elasticsearch:首先确保你已经安装了 Elasticsearch 并且它正在运行。你可以从 Elasticsearch 的官方网站上下载并安装它。
- 安装 Haystack:确保你已经安装了 Django Haystack。你可以使用 pip 进行安装:
pip install django-haystack
。 - 安装 Elasticsearch 后端:你需要安装与 Elasticsearch 兼容的 Haystack 后端。通常情况下,你需要安装
elasticsearch-dsl
,它是 Elasticsearch 的 Python 客户端库。你可以使用 pip 进行安装:pip install elasticsearch-dsl
。 - 配置 Haystack 设置:在 Django 项目的
settings.py
文件中,配置 Haystack 设置以使用 Elasticsearch 后端。这包括指定 Elasticsearch 的主机和端口等信息。
HAYSTACK_CONNECTIONS = {'default': {'ENGINE': 'haystack.backends.elasticsearch_backend.ElasticsearchSearchEngine','URL': 'http://localhost:9200/', # Elasticsearch 服务器的 URL'INDEX_NAME': 'haystack', # Elasticsearch 索引的名称},
}
- 建立索引:运行
python manage.py rebuild_index
命令来建立你的模型的搜索索引。这将会在 Elasticsearch 中创建对应的索引。 - 运行你的应用程序:现在你的 Django 应用程序应该能够连接到 Elasticsearch 并使用它来进行全文搜索了。
问题和解决
报错 from django.utils.datetime_safe import date, datetime ModuleNotFoundError: No module named 'django.utils.datetime_safe'
分析解决:
在 Django 3.2 中,django.utils.datetime_safe
模块已被移除。这个模块提供了在处理日期和时间时的安全操作,以防止由于 datetime
和 date
对象的类型不同而导致的一些问题。
如果你的代码中依赖了 django.utils.datetime_safe
模块,你可以尝试以下替代方法:
- 直接使用 datetime 和 date:在绝大多数情况下,直接使用内置的
datetime
和date
类应该没有问题。只要确保在处理日期和时间时,类型的转换和比较是正确的即可。 - 在需要的地方进行转换:如果你的代码在某些情况下需要确保
datetime
和date
对象的类型一致,你可以手动进行转换。比如,使用timezone.now()
获取当前时间,使用datetime.strptime()
将字符串转换为datetime
对象等。 - 更新依赖:如果你使用的是第三方库,可以尝试更新这些库的版本,看看是否有与 Django 3.2 兼容的版本。
确保你的代码不再依赖于 django.utils.datetime_safe
模块后,就可以解决这个错误了。切换为elasticsearch
连接。报错如下 raise MissingDependency( haystack.exceptions.MissingDependency: The 'elasticsearch5' backend requires the installation of 'elasticsearch>=5.0.0,<6.0.0'. Please refer to the documentation.
修改settings.py
中HAYSTACK_CONNECTIONS
连接的Elasticsearch
版本为8.x,如下:
HAYSTACK_CONNECTIONS = {'default': {'ENGINE': 'haystack.backends.elasticsearch8_backend.Elasticsearch8SearchEngine','URL': 'http://localhost:9200/','INDEX_NAME': 'myblog',},
}
报错ModuleNotFoundError: No module named 'haystack.backends.elasticsearch8_backend'
原因:Haystack
中没有提供一个专门用于Elasticsearch
8.x 的后端引擎。使用 haystack.backends.elasticsearch7_backend.Elasticsearch7SearchEngine
就可以支持 Elasticsearch
7.x。
重新安装elasticsearch
版本号为7.17。见这篇文章
卸载不需要的驱动
pip uninstall elasticsearch
pip uninstall elasticsearch-dsl
安装需要的驱动
pip install elasticsearch==7.17.0pip install elasticsearch-dsl==7.4.1
再次调用启动搜索index
命令python manage.py rebuild_index
报错ImportError: cannot import name 'datetime_safe' from 'django.utils'
原因:Django 3.2 中移除了 django.utils.datetime_safe
模块引起的。Haystack 应该已经更新以适应 Django 3.2。
执行命令下载haystack支持django5.0.7
pip install git+https://github.com/django-haystack/django-haystack.git
再次调用启动搜索index
命令
python manage.py rebuild_index
运行成功。效果如下:
调用http://localhost:8000/search/?q=%E6%AF%94%E4%BC%AF
后,结果如下:
分析原因elasticsearch
的index有问题。
用tree /F
命令获取全文件夹下的文件格式表。
通过下面命令获取当前elasticsearch
里面的index
:
Invoke-WebRequest -Uri "http://localhost:9200/_cat/indices?v"
在post_text.txt
里面添加一段index
的指向
<!-- templates/search/indexes/blog/post_text.txt -->
执行index命令python manage.py rebuild_index
执行成功,如下:
postman
调用apihttp://localhost:9200/myblog
结果返回成功:
{"myblog": {"aliases": {},"mappings": {"properties": {"content": {"type": "text","analyzer": "snowball"},"django_ct": {"type": "keyword"},"django_id": {"type": "keyword"},"id": {"type": "text","fields": {"keyword": {"type": "keyword","ignore_above": 256}}},"text": {"type": "text","analyzer": "snowball"},"title": {"type": "text","analyzer": "snowball"}}},"settings": {"index": {"max_ngram_diff": "2","routing": {"allocation": {"include": {"_tier_preference": "data_content"}}},"number_of_shards": "1","provided_name": "myblog","creation_date": "1716964128114","analysis": {"filter": {"haystack_ngram": {"type": "ngram","min_gram": "3","max_gram": "4"},"haystack_edgengram": {"type": "edge_ngram","min_gram": "2","max_gram": "15"}},"analyzer": {"edgengram_analyzer": {"filter": ["haystack_edgengram","lowercase"],"tokenizer": "standard"},"ngram_analyzer": {"filter": ["haystack_ngram","lowercase"],"tokenizer": "standard"}}},"number_of_replicas": "1","uuid": "1GzZNjZzSmOtmFdLuGWhvw","version": {"created": "7170099"}}}}
}
搜索index
修改搜索视图以获取匹配的博客文章 ID,并从 MySQL 中获取详细信息:
# blog/views.py
from django.shortcuts import render
from haystack.query import SearchQuerySet
from .models import BlogPost
from .forms import BlogSearchFormdef search(request):form = BlogSearchForm(request.GET)results = []if form.is_valid():# 从 Elasticsearch 获取匹配的博客文章 IDsqs = form.search()matched_ids = [result.pk for result in sqs]# 从 MySQL 数据库中获取详细信息results = BlogPost.objects.filter(id__in=matched_ids)return render(request, 'search_results.html', {'form': form, 'results': results})
访问’http://localhost:8000’输入搜索growing,访问’http://localhost:8000/search/?q=growing’,得到结果如下:
相关文章:

基于Django的博客系统之用HayStack连接elasticsearch增加搜索功能(五)
上一篇:搭建基于Django的博客系统数据库迁移从Sqlite3到MySQL(四) 下一篇:基于Django的博客系统之增加类别导航栏(六) 功能概述 添加搜索框用于搜索博客。 需求详细描述 1. 添加搜索框用于搜索博客 描…...

开源VS闭源:大模型发展路径之争,你站哪一派?
文章目录 引言一、数据隐私1.1开源大模型的数据隐私1.2 闭源大模型的数据隐私1.3 综合考量 二、商业应用2.1 开源大模型的商业应用2.2 闭源大模型的商业应用2.3 商业应用的综合考量 三、社区参与3.1 开源大模型的社区参与3.2 闭源大模型的社区参与3.3 综合考量 结论 引言 在人…...

Python | Leetcode Python题解之第115题不同的子序列
题目: 题解: class Solution:def numDistinct(self, s: str, t: str) -> int:m, n len(s), len(t)if m < n:return 0dp [[0] * (n 1) for _ in range(m 1)]for i in range(m 1):dp[i][n] 1for i in range(m - 1, -1, -1):for j in range(n …...

STM32高级控制定时器应用之检测输入PWM周期和占空比
目录 概述 1 PWM 输入模式 1.1 原理介绍 1.2 应用实例 1.3 示例时序图 2 使用STM32Cube配置工程 2.1 软件环境 2.2 配置参数 2.3 生成项目文件 3 功能实现 3.1 PWM占空比函数 3.2 输入捕捉回调函数 4 功能测试 4.1 测试软件框架结构 4.2 实验实现 4.2.1 测试实…...

[AI Google] 三种新方法利用 Gemini 提高 Google Workspace 的生产力
Workspace 侧边栏中的 Gemini 现在将使用 Gemini 1.5 Pro,新的 Gemini for Workspace 功能即将登陆 Gmail 移动应用,等等。 Gemini for Google Workspace 帮助个人和企业更好地利用 Google 应用——从在 Gmail 中撰写邮件到在 Sheets 中组织项目计划。过…...

【U-Net验证】逐元素乘积将特征投射到极高维隐式特征空间的能力
写在前面:本博客仅作记录学习之用,部分图片来自网络,如需使用请注明出处,同时如有侵犯您的权益,请联系删除! 文章目录 前言网络结构编码结构解码结构代码 实验实验设置w/o-ReLU的性能比较with-ReLU的性能比…...

快团团大团长帮卖如何导出单个团购的订单?免费教程教你怎么做!
一、小程序端如何导出单个团购的订单? 进入团购页面,在订单管理——订单导出中,点击订单数据表格,可导出到邮箱,或通过在浏览器中查看下载链接 二、电脑端如何导出单个团购的订单? 1、如何自定义选择订单信…...

services层和controller层
services层 我的理解,services层是编写逻辑代码语句最多的一个层,非常重要,在实际的项目中,负责调用Dao层中的mybatis,在我的项目中它调用的是这两个文件 举例代码如下 package com.example.sfdeliverysystem.servic…...
Pycharm编辑器下自定义模块导入报错:no module named问题
相信很多使用pycharm 社区版编写python 程序的初学者都会遇到这样一个看似简单但是一时半刻找不到解决头绪的问题: 在同个目录下导入自己编写的模块到主程序的过程中,直接import的时候会报错:ModuleNotFoundError。 通过各种方法尝试以后还是…...

C#使用GDI对一个矩形进行任意角度旋转
C#对一个矩形进行旋转GDI绘图,可以指定任意角度进行旋转 我们可以认为一张图片Image,本质就是一个矩形Rectangle,旋转矩形也就是旋转图片 在画图密封类 System.Drawing.Graphics中, 矩形旋转的两个关键方法 //设置旋转的中心点 public v…...

打印机的ip不同且连不上
打印机的ip不同且连不上 1.问题分析2.修改网段3.验证网络 1.问题分析 主要是打印机的网段和电脑不在同一个网段 2.修改网段 3.验证网络...

关于linux程序的查看、前台运行、后台运行、杀死的管理操作。
前言 在Linux中, 程序(program)是放在磁盘上的程序,是不会执行的。 进程(process)是程序被触发,从而加载到内存中的,会被CPU随机执行。 Linux中,有非常多的进程在实时运…...

STM32作业设计
目录 STM32作业设计 STM32作业实现(一)串口通信 STM32作业实现(二)串口控制led STM32作业实现(三)串口控制有源蜂鸣器 STM32作业实现(四)光敏传感器 STM32作业实现(五)温湿度传感器dht11 STM32作业实现(六)闪存保存数据 STM32作业实现(七)OLED显示数据 STM32作业实现(八)触摸按…...

PHPSTOM配置Laradock,xdebug,phpunit
原理图: 片面理解: phpstorm启用一个9000端口,这个端口用来接收到信息后,启用xdebug功能。服务器端(docker), 当客户端访问laravel项目域名后, 并读取xdebug.ini的配置, 把调试的请求数据, 向配置里面的端口发送消息, 配置里面的端…...
使用Java进行数据分析和处理:应用在实际业务场景中的技术
在当今数据驱动的时代,数据分析和处理已经成为各行各业中不可或缺的一部分。Java作为一种广泛应用于企业级开发的编程语言,也在数据领域展现出了强大的能力。本文将探讨如何使用Java进行数据分析和处理,以及在实际业务场景中应用的技术。 ##…...
C++中的List
摘要 C 标准库中的 std::list 是一种双向链表容器,它允许在常数时间内进行插入和删除操作,每个元素包含一个指向前一个和后一个元素的指针。这给我们开发提供了高效的插入和删除操作。 引入头文件 要使用 std::list,需要包含头文件 <li…...
go map 如何比较两个 map 相等
go map 如何比较两个 map 相等 都为 nil非空、长度相等,指向同一个 map 实体对象相应的 key 指向的 value 相等 直接将使用 map1 map2 是错误的。这种写法只能比较 map 是否为 nil。因此只能是遍历map 的每个元素,比较元素是否都是深度相等。...

牛客网刷题 | BC108 反斜线形图案
目前主要分为三个专栏,后续还会添加: 专栏如下: C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读! 初来乍到,如有错误请指出,感谢! 描述 KiKi学习了循环&am…...

数据的表示和运算
目录 一.各进制间的相互转换 1.各进制转化为10进制 2.二进制和八进制,十六进制之间地相互转化 3.十进制转换为其他进制 二.BCD码(Binary-Coded Decimal,用二进制编码的十进制) 1.8421码 2.余3码 3.2421码 三.无符号整数 …...

【爬虫工具】油管视频批量采集软件
一、背景介绍 1.1 爬取目标 我用Python独立开发了一款爬虫软件,作用是:通过搜索关键词采集ytb的搜索结果,包含14个关键字段:关键词,页码,视频标题,视频id,视频链接,发布时间,视频时长,频道名称,频道id,频道链接,播放数,点赞数,评…...

测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...

装饰模式(Decorator Pattern)重构java邮件发奖系统实战
前言 现在我们有个如下的需求,设计一个邮件发奖的小系统, 需求 1.数据验证 → 2. 敏感信息加密 → 3. 日志记录 → 4. 实际发送邮件 装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

树莓派超全系列教程文档--(61)树莓派摄像头高级使用方法
树莓派摄像头高级使用方法 配置通过调谐文件来调整相机行为 使用多个摄像头安装 libcam 和 rpicam-apps依赖关系开发包 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 配置 大多数用例自动工作,无需更改相机配置。但是,一…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】
1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件(System Property Definition File),用于声明和管理 Bluetooth 模块相…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...