格搜索
要求的功能:基础版本——字符串比较 忽略大小写——大小写转换 模糊搜索——search的使用 多关键词——split 高亮显示、筛选
符合百度搜索的要求
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script>
window.onload=function (){
var oTab=document.getElementById('tab1');
var oTxt=document.getElementById('name');
var oBtn=document.getElementById('btn1');
oBtn.onclick=function (){
for(var i=0;i<oTab.tBodies[0].rows.length;i++){
var sTab=oTab.tBodies[0].rows[i].cells[1].innerHTML.toLowerCase();
var sTxt=oTxt.value.toLowerCase();
var arr=sTxt.split(' ');
oTab.tBodies[0].rows[i].style.display='none';
for(var j=0;j<arr.length;j++){
if(sTab.search(arr[j])!=-1){
oTab.tBodies[0].rows[i].style.display='block';
}
}
}
};
};
</script>
</head>
<body>
姓名:<input id="name" type="text" />
<input id="btn1" type="button" value="搜索" />
<table id="tab1" border="1" width="500">
<thead>
<td>ID</td>
<td>姓名</td>
<td>年龄</td>
<td>操作</td>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Blue</td>
<td>27</td>
<td></td>
</tr>
<tr>
<td>2</td>
<td>张三</td>
<td>23</td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>李四</td>
<td>28</td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>王五</td>
<td>25</td>
<td></td>
</tr>
<tr>
<td>5</td>
<td>张伟</td>
<td>24</td>
<td></td>
</tr>
<tr>
<td>6</td>
<td>王四</td>
<td>24</td>
<td></td>
</tr>
</tbody>
</table>
</body>
</html>
以下为简单版本
版本1:基础版本——字符串比较
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script>
window.onload=function (){
var oTab=document.getElementById('tab1');
var oTxt=document.getElementById('name');
var oBtn=document.getElementById('btn1');
oBtn.onclick=function (){
for(var i=0;i<oTab.tBodies[0].rows.length;i++){
if(oTab.tBodies[0].rows[i].cells[1].innerHTML==oTxt.value){
oTab.tBodies[0].rows[i].style.background='yellow';
}
else{
oTab.tBodies[0].rows[i].style.background='';
}
}
};
};
</script>
</head>
<body>
姓名:<input id="name" type="text" />
<input id="btn1" type="button" value="搜索" />
<table id="tab1" border="1" width="500">
<thead>
<td>ID</td>
<td>姓名</td>
<td>年龄</td>
<td>操作</td>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Blue</td>
<td>27</td>
<td></td>
</tr>
<tr>
<td>2</td>
<td>张三</td>
<td>23</td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>李四</td>
<td>28</td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>王五</td>
<td>25</td>
<td></td>
</tr>
<tr>
<td>5</td>
<td>张伟</td>
<td>24</td>
<td></td>
</tr>
</tbody>
</table>
</body>
</html>
版本2:忽略大小写——大小写转换
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script>
window.onload=function (){
var oTab=document.getElementById('tab1');
var oTxt=document.getElementById('name');
var oBtn=document.getElementById('btn1');
oBtn.onclick=function (){
for(var i=0;i<oTab.tBodies[0].rows.length;i++){
var sTab=oTab.tBodies[0].rows[i].cells[1].innerHTML;
var sTxt=oTxt.value;
if(sTab.toLowerCase()==sTxt.toLowerCase()){
oTab.tBodies[0].rows[i].style.background='yellow';
}
else{
oTab.tBodies[0].rows[i].style.background='';
}
}
};
};
</script>
</head>
<body>
姓名:<input id="name" type="text" />
<input id="btn1" type="button" value="搜索" />
<table id="tab1" border="1" width="500">
<thead>
<td>ID</td>
<td>姓名</td>
<td>年龄</td>
<td>操作</td>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Blue</td>
<td>27</td>
<td></td>
</tr>
<tr>
<td>2</td>
<td>张三</td>
<td>23</td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>李四</td>
<td>28</td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>王五</td>
<td>25</td>
<td></td>
</tr>
<tr>
<td>5</td>
<td>张伟</td>
<td>24</td>
<td></td>
</tr>
</tbody>
</table>
</body>
</html>
版本3:模糊搜索——search的使用
<html>
<head>
<meta charset="utf-8">
<title>无标题文档</title>
<script>
window.onload=function (){
var oTab=document.getElementById('tab1');
var oTxt=document.getElementById('name');
var oBtn=document.getElementById('btn1');
oBtn.onclick=function (){
for(var i=0;i<oTab.tBodies[0].rows.length;i++){
var sTab=oTab.tBodies[0].rows[i].cells[1].innerHTML.toLowerCase();
var sTxt=oTxt.value.toLowerCase();
if(sTab.search(sTxt)!=-1){
oTab.tBodies[0].rows[i].style.background='yellow';
}
else{
oTab.tBodies[0].rows[i].style.background='';
}
}
};
};
</script>
</head>
<body>
姓名:<input id="name" type="text" />
<input id="btn1" type="button" value="搜索" />
<table id="tab1" border="1" width="500">
<thead>
<td>ID</td>
<td>姓名</td>
<td>年龄</td>
<td>操作</td>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Blue</td>
<td>27</td>
<td></td>
</tr>
<tr>
<td>2</td>
<td>张三</td>
<td>23</td>
<td></td>
</tr>
<tr>
<td>3</td>
<td>李四</td>
<td>28</td>
<td></td>
</tr>
<tr>
<td>4</td>
<td>王五</td>
<td>25</td>
<td></td>
</tr>
<tr>
<td>5</td>
<td>张伟</td>
<td>24</td>
<td></td>
</tr>
<tr>
<td>6</td>
<td>王四</td>
<td>24</td>
<td></td>
</tr>
</tbody>
</table>
</body>
</html>
版本4:多关键词——split
文介绍了一种新的HTML元素搜索方法,并提供了一个实用的工具来帮助开发者快速找到所需的元素。这对于那些需要处理大量HTML元素的开发者来说是非常有用的。文章还通过提供一些常见元素的用法示例,帮助开发者更好地理解和应用这些元素。在众多元素中找到特定的元素。为了解决这个问题,文章介绍了一种新的HTML元素搜索方法。
下面是正文
一个新的语义元素已经加入了 HTML 标准。它代表文档中用于搜索或过滤的部分。它应该包含表单控件(如文本输入、下拉菜单、按钮等),搜索/过滤的范围可以是任何内容:从同一文档到整个互联网。
在 <search> 元素之前,我们可以在 <form> 标签中添加 role="search" 以指示该表单用于搜索:
<form role="search" method="get" action="/search">
<input type="search" name="search-text" />
<button>Search</button>
</form>
有了这个新添加的功能,我们可以使用 <search> 标签来包装表单:
由于 <search> 是标准中的新内容,所有浏览器、屏幕阅读器和其他工具可能需要一段时间才能跟上。在此期间,我们可以使用一个 hack,指定它已经具有的 ARIA 角色(类似于 <nav> 所发生的情况)。这在未来可能会变得多余,但它可能会为我们的代码做好准备,以便在浏览器支持新标签时使用。
<search role="search">
...
</search>
这看起来有些违反直觉:我们正在移除 role="search" ,但我们正在用<search>包装所有内容。总体而言,这是更多的文本/代码(仅三个字符)和更多的嵌套(一个更高的级别)。
温馨提示:尽管我们在构建搜索组件时并不强制需要
标签,但是使用它却能带来额外的好处(甚至是必须的)。这样,即使在无JavaScript环境下,搜索功能也能保持正常运行,或者说,这是一种实践渐进式增强策略的方式。
另一个需要注意的关键点是,搜索区域不一定是网站或在线平台上带有搜索按钮的文本输入框。我们可以使用 <search> 来过滤结果或表格行。它的实用性不仅限于文本输入和搜索框:
<search>
<h2>Filter results</h2>
<form>
<label for="cartype">Car type</label>
<select id="cartype">
<option value="coupe">Coupe</option>
<option value="sedan">Sedan</option>
</select>
<label for="electric">Electric?</label>
<input type="checkbox" id="electric" />
</form>
</search>
拥有一个用于识别搜索区域的元素是很好的。正如Scott O'Hara在这篇文章中指出的那样,直到现在,这是唯一一个在HTML中没有语义等效项的ARIA地标角色:
使用 <search> 来标识应具有“搜索”角色的部分,我们将使用一些语义化的 HTML 元素覆盖所有 ARIA 地标角色。这很棒:它将提高可访问性(尽管如上所述,需要一段时间才能让所有浏览器跟上),并扩展了语言的语义。
但是,从程序员的角度来看,它感觉不够完善或没有为现有的实现增加太多东西。其他语义元素可以提高可访问性并简化我们编写特定组件的方式。例如,像 <tabpanel> 和 <tab> 这样的东西,在我看来会更具说服力和价值。
这并不会削弱它的重要性。所有的改进 - 即使是微小的改进 - 都是受欢迎的。这也适用于 <search> 。这是 HTML 家族的一个极好的新成员。
者:HelloGitHub-追梦人物
搜索是一个复杂的功能,但对于一些简单的搜索任务,我们可以使用 Django Model 层提供的一些内置方法来完成。现在我们来为我们的博客提供一个简单的搜索功能。
博客文章通常包含标题和正文两个部分。当用户输入某个关键词进行搜索后,我们希望为用户显示标题和正文中含有被搜索关键词的全部文章。整个搜索的过程如下:
整个过程就是这样,下面来看看 Django 如何用实现这些过程。
先来回顾一下我们的 Django 博客的 Post(文章)模型:
blog/models.py
class Post(models.Model):
# 标题
title = models.CharField("标题", max_length=70)
# 正文
body = models.TextField("正文")
# 其他属性...
def __str__(self):
return self.title
先看到第 1 步,用户在搜索框输入搜索关键词,因此我们要在博客上为用户提供一个搜索表单,HTML 表单代码大概像这样:
templates/base.html
<form role="search" method="get" id="searchform" action="{% url 'blog:search' %}">
<input type="search" name="q" placeholder="搜索" required>
<button type="submit"><span class="ion-ios-search-strong"></span></button>
</form>
特别注意这里 <input type="search" name="q" placeholder="搜索" required> 中的 name 属性,当用户在这个 input 中输入搜索内容并提交表单后,键入的数据会以键值对的形式提交服务器,这个键的名字就是通过 name 属性指定的。这样服务器就可以根据 name 的值来取得用户输入的内容。
用户输入了搜索关键词并点击了搜索按钮后,数据就被发送给了 Django 后台服务器。表单的 action 属性的值为 {% url 'blog:search' %}(虽然我们还没有写这个视图函数),表明用户提交的结果将被发送给 blog 应用下 search 视图函数对应的 URL。
搜索的功能将由 search 视图函数提供,代码写在 blog/views.py 里:
blog/views.py
from django.contrib import messages
def search(request):
q = request.GET.get('q')
if not q:
error_msg = "请输入搜索关键词"
messages.add_message(request, messages.ERROR, error_msg, extra_tags='danger')
return redirect('blog:index')
post_list = Post.objects.filter(Q(title__icontains=q) | Q(body__icontains=q))
return render(request, 'blog/index.html', {'post_list': post_list})
首先我们使用 request.GET.get('q') 获取到用户提交的搜索关键词。用户通过表单 get 方法提交的数据 Django 为我们保存在 request.GET 里,这是一个类似于 Python 字典的对象,所以我们使用 get 方法从字典里取出键 q 对应的值,即用户的搜索关键词。这里字典的键之所以叫 q 是因为我们的表单中搜索框 input 的 name 属性的值是 q,如果修改了 name 属性的值,那么这个键的名称也要相应修改。
接下来我们做了一个小小的校验,如果用户没有输入搜索关键词而提交了表单,我们就无需执行查询,我们给给用户发一条错误提醒消息,这里使用了 django messages 应用,这在 交流的桥梁:评论功能中讲过。然后将用户重定向到首页。这里的 redirect 函数也在那篇教程中讲过。
如果用户输入了搜索关键词,我们就通过 filter 方法从数据库里过滤出符合条件的所有文章。这里的过滤条件是 title__icontains=q,即 title 中包含(contains)关键字 q,前缀 i 表示不区分大小写。这里 icontains 是查询表达式(Field lookups),我们在之前也使用过其他类似的查询表达式,其用法是在模型需要筛选的属性后面跟上两个下划线。Django 内置了很多查询表达式,建议过一遍 Django 官方留个印象,了解每个表达式的作用,以后碰到相关的需求就可以快速定位到文档查询其用途 Field lookups。
此外我们这里从 from django.db.models 中引入了一个新的东西:Q 对象。Q 对象用于包装查询表达式,其作用是为了提供复杂的查询逻辑。例如这里 Q(title__icontains=q) | Q(body__icontains=q) 表示标题(title)含有关键词 q 或者正文(body)含有关键词 q ,或逻辑使用 | 符号。如果不用 Q 对象,就只能写成 title__icontains=q, body__icontains=q,这就变成标题(title)含有关键词 q 且正文(body)含有关键词 q,就达不到我们想要的目的。
有了视图函数后记得把视图函数映射到相应了 URL,如下。
blog/urls.py
urlpatterns = [
# 其他 url 配置
path('search/', views.search, name='search'),
]
大功告成,在导航栏尝试输入一些关键词,看看效果吧!
当然这样的搜索功能是非常简略的,难以满足一些复杂的搜索需求。编写一个搜索引擎是一个大工程,好在 django-haystack 这款第三方 app 为我们完成了全部工作。使用它我们可以实现更加复杂的搜索功能,比如全文检索、按搜索相关度排序、关键字高亮等等类似于百度搜索的功能,功能十分强大。当然其使用也会复杂一些,下一篇教程将向大家介绍 django-haystack 结合 Elasticsearch 搜索引擎的使用方法。
『讲解开源项目系列』——让对开源项目感兴趣的人不再畏惧、让开源项目的发起者不再孤单。跟着我们的文章,你会发现编程的乐趣、使用和发现参与开源项目如此简单。欢迎留言联系我们、加入我们,让更多人爱上开源、贡献开源
*请认真填写需求信息,我们会在24小时内与您取得联系。