一、样式:

django-haystack在utils模块中封装了HighHighlighter用于配置搜索结果的样式展示。想要更改结果的样式,可以写个子类重写相应的方法达到效果

1.关键字高亮:

HighHighlighter为模版文件提供了搜索关键字相关的配置信息,只需在模版文件search.html中使用即可

 1 # 关键字高亮分为三步:
2 # 1.模版引用
3 {% load highlight %}
4
5 # 2.改变模版变量的填充方式
6 # 改变写法后,higtlight会为原结果中的关键字部分添一个span标签,并设置class为highlighted
7 # 改变前
8 {{ item.object.title }}
9 # 改变后
10 {% highlight item.object.title with query %}
11
12 # 3.给关键字设置样式
13 <style>
14 span.highlighted {
15 color: red;
16 }
17 </style>

效果如下:

注:我这里改了关键字显示位置,原生的django-haystack的搜索结果是会以 ... 开头,然后拼接关键字以及后面部分的。

2.关键字显示位置:

通过改变HighHighlighter类的find_window方法可改变关键字显示位置,具体实现如下:

 1 # 1.定义子类继承,并重写find_window方法
2 class MyHighlighter(Highlighter):
3 """自定义Highlighter,改变高亮部分前面文本长度"""
4 def find_window(self, highlight_locations):
5 best_start = 0
6 best_end = self.max_length
7
8 # First, make sure we have words.
9 if not len(highlight_locations):
10 return (best_start, best_end)
11
12 words_found = []
13
14 # Next, make sure we found any words at all.
15 for word, offset_list in highlight_locations.items():
16 if len(offset_list):
17 # Add all of the locations to the list.
18 words_found.extend(offset_list)
19
20 if not len(words_found):
21 return (best_start, best_end)
22
23 if len(words_found) == 1:
24 # 查找内容中只找到一个query
25 best_start = words_found[0]
26 best_end = words_found[0] + self.max_length
27
28 if best_end > len(self.text_block):
29 move_forward_steps = best_end - len(self.text_block)
30 best_start -= move_forward_steps
31
32 if best_start < 0:
33 best_start = 0
34
35 return (best_start, best_end)
36
37 # 2.django的settings文件中自定义Highlighter类
38 HAYSTACK_CUSTOM_HIGHLIGHTER = 'utils.haystack_custom.MyHighlighter'

效果如上图

二、搜索频率限制:

跟踪haystack.urls可以知道,Django-haystack的视图定义在SearchView这个类中

1 # haystack.urls.py
2
3 urlpatterns = [
4 url(r'^$', SearchView(), name='haystack_search'),
5 ]

urls.py中将SearchView的类对象直接作为视图函数,当搜索请求来的时候,将会执行SearchView类的__call__方法,__call__方法源码如下:

 1     def __call__(self, request):
2 """
3 Generates the actual response to the search.
4
5 Relies on internal, overridable methods to construct the response.
6 """
7 # 获取request对象
8 self.request = request
9
10 # 获取form中的参数
11 self.form = self.build_form()
12 # 校验form参数
13 self.query = self.get_query()
14 # 生成搜索结果
15 self.results = self.get_results()
16
17 # 返回视图
18 return self.create_response()

那么,可以写个子类继承SearchView类,在SearchView类的__call__方法执行之前,从request对象中获取到用户ip,然后对ip做频率限制即可实现我们的需求,实现如下:

 1 # 1.写个子类继承SearchView类,重写__call__方法
2
3 # 导入这里就不说了
4 class MySearchView(SearchView):
5 """自定义search视图函数,添加IP搜索频率限制"""
6 def __call__(self, request):
7 # 获取用户IP
8 ip = request.META.get("REMOTE_ADDR", "")
9 if ip == "":
10 return super(MySearchView, self).__call__(request)
11
12 try:
13 has_search_flag = cache.get("has_search_%s" % ip)
14 except Exception as e:
15 settings.LOGGER.error(e)
16 return super(MySearchView, self).__call__(request)
17 else:
18 if has_search_flag is None:
19 cache.set("has_search_%s" % ip, 1, settings.SEARCH_FREQUENCY_FORBID_TIME)
20 return super(MySearchView, self).__call__(request)
21
22 return render(request, 'search/search.html', {"errmsg":"您的操作过于频繁,请稍后再试"})
23
24 # 2.修改路由匹配
25
26 # 导入这里就不说了
27 urlpatterns = [
28 # path('search', include('haystack.urls')), # 全文检索框架
29 path('search', MySearchView(), name="haystack_search"), # 全文检索框架
30 ]

------------------------------

更新:当搜索结果分页后,用户点击下一页或上一页,是会改变page参数重新发起请求的,这里也会视为频繁操作,那就有问题了。

于是逻辑修改如下:将缓存中的从固定的1改成存关键字,下次搜索关键字变更了的情况下才加以限制,实现如下:

 1 class MySearchView(SearchView):
2 """自定义search视图函数,添加IP搜索频率限制"""
3 def __call__(self, request):
4 # 获取用户IP
5 search_q = request.GET.get("q", None)
6 if search_q is None:
7 return render(request, 'search/search.html', {"errmsg":"参数有误"})
8
9 ip = request.META.get("REMOTE_ADDR", "")
10 if ip == "":
11 return super(MySearchView, self).__call__(request)
12
13 try:
14 has_search_flag = cache.get("has_search_%s" % ip)
15 except Exception as e:
16 settings.LOGGER.error(e)
17 return super(MySearchView, self).__call__(request)
18 else:
19 if has_search_flag:
20 if has_search_flag != search_q:
21 return render(request, 'search/search.html', {"errmsg":"您的操作过于频繁,请稍后再试"})
22 else:
23 return super(MySearchView, self).__call__(request)
24 else:
25 cache.set("has_search_%s" % ip, search_q, settings.SEARCH_FREQUENCY_FORBID_TIME)
26 return super(MySearchView, self).__call__(request)

拓展django-haystack全文检索的样式和搜索频率限制的更多相关文章

  1. Django Haystack 全文检索与关键词高亮

    Django Haystack 简介 django-haystack 是一个专门提供搜索功能的 django 第三方应用,它支持 Solr.Elasticsearch.Whoosh.Xapian 等多 ...

  2. django使用haystack对接Elasticsearch实现商品搜索

    # 原创,转载请留言联系 前言: 在做一个商城项目的时候,需要实现商品搜索功能. 说到搜索,第一时间想到的是数据库的 select * from tb_sku where name like %苹果手 ...

  3. django haystack报错: ModuleNotFoundError: No module named 'blog.whoosh_cn_backend'

    在配置django haystack时报错: 解决方案: 将ENGINE的值 改为 这样就可以了.

  4. django在style的样式image url添加静态图片路径和django如何动态传入图片链接?

    #django在style的样式image url添加静态图片路径 style=" background:url({% static "agribusiness/images/lo ...

  5. Android FM模块学习之二 FM搜索频率流程

    上一篇大概分析了一下FM启动流程,若不了解Fm启动流程的,能够去打开前面的链接先了解FM启动流程,接下来我们简单分析一下FM的搜索频率流程. 在了解源代码之前.我们先看一下流程图: 事实上从图中能够看 ...

  6. Django:haystack全文检索详细教程

    参考:https://blog.csdn.net/AC_hell/article/details/52875927 一.安装第三方库及配置 1.1 安装插件 pip install whoosh dj ...

  7. haystack(django的全文检索模块)

    haystack haystack是django开源的全文搜索框架 全文检索:标题可以检索,内容也可以检索 支持solr ,elasticsearch,whoosh 1.注册app 在setting. ...

  8. 08: Django使用haystack借助Whoosh实现全文搜索功能

    参考文章01:http://python.jobbole.com/86123/ 参考文章02: https://segmentfault.com/a/1190000010866019 参考官网自定制v ...

  9. Django+haystack实现全文搜索出现错误 ImportError: cannot import name signals

    原因是在你的settings.py或者其他地方使用了  "import haystack" 当我们使用django-haysatck库时,表面上会有haystack库,但实际上并不 ...

  10. Haystack全文检索

    1.什么是Haystack Haystack是django的开源全文搜索框架(全文检索不同于特定字段的模糊查询,使用全文检索的效率更高 ),该框架支持Solr,Elasticsearch(java写的 ...

随机推荐

  1. java LinkedList 原理

    概述 底层数据结构是双向链表(jdk1.6是双向循环,1.7开始不循环了),所以 新增/删除效率高,查询/修改效率相对较低 全能冠军:既是一个顺序容器,也是队列,还可以作为栈使用 未实现 Random ...

  2. C++——第三方插件

    EasyX库安装教程 官网:https://easyx.cn/ 下载地址:EasyX Graphics Library for C++ 作品:CodeBus - 分享有趣的 C/C++ 代码 图中标注 ...

  3. postgresql 学习链接

    1.菜鸟教程:https://www.runoob.com/postgresql/postgresql-operators.html 2.易百教程:https://www.yiibai.com/pos ...

  4. nginx从仅支持80到支持80和443

    测试环境的域名,之前只支持http.开发同学不知啥时候改了数据库配置,导致所有跳转到到了https了.所以得加上https访问. 配置文件之前是这样的: 1 server { 2 listen 80; ...

  5. POD一些概念

    以FAQ的方式来加强对POD的理解: 1.重启了一台机器,之后运行了13天,我看到pod的age并不是我以为的5d,而是远远大于5d.这是因为pod的age,主要是关注uid有没有变化,没有则不会更新 ...

  6. python之路3:文件操作和函数基础

    文件操作 字符编码解码 函数基础 内置函数 一.文件操作 对文件操作流程 打开文件,得到文件句柄并赋值给一个变量 通过句柄对文件进行操作 关闭文件 打开文件的模式有: r,只读模式(默认). w,只写 ...

  7. 【情景题】NPDP经典题目(上)

    [情景题]NPDP经典题目(上) 1.一家玩具生产企业正在为10-12岁的儿童开发一种"动力车".潜在风险:尽管该公司在玩具市场有着丰富的经验,但是这些经验主要是针对5岁以下儿童玩 ...

  8. 蓝桥杯训练赛二-1199 问题 E: 哥德巴赫曾猜测

    题目描述 德国数学家哥德巴赫曾猜测:任何大于6的偶数都可以分解成两个素数(素数对)的和.但有些偶数可以分解成多种素数对的和,如: 10=3+7,10=5+5,即10可以分解成两种不同的素数对 输入 输 ...

  9. Android拍照程序适配

    public void takePic(){ String forderPath = getExternalFilesDir("") + "/pic"; Fil ...

  10. Linux安装证书

    Linux安装 vCenter root CA: 1.访问vCenter管理页面,下载"下载受信任的根 CA 证书" 2.压缩文件内带有数字作为扩展名(.0..1 等)的文件是根证 ...