文中所涉及的示例代码,已同步更新到HelloGitHub-Team 仓库

搜索是一个复杂的功能,但对于一些简单的搜索任务,我们可以使用 Django Model 层提供的一些内置方法来完成。现在我们来为我们的博客提供一个简单的搜索功能。

概述

博客文章通常包含标题和正文两个部分。当用户输入某个关键词进行搜索后,我们希望为用户显示标题和正文中含有被搜索关键词的全部文章。整个搜索的过程如下:

用户在搜素框中输入搜索关键词,假设为 “django”,然后用户点击了搜索按钮提交其输入的结果到服务器。服务器接收到用户输入的搜索关键词 “django” 后去数据库查找文章标题和正文中含有该关键词的全部文章。服务器将查询结果返回给用户。

整个过程就是这样,下面来看看 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 的值来取得用户输入的内容。

用户输入了搜索关键词并点击了搜索按钮后,QQ号码买卖数据就被发送给了 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

有了视图函数后记得把视图函数映射到相应了 URL,如下。

blog/urls.py urlpatterns = [ # 其他 url 配置 path('search/', views.search, name='search'), ] 复制代码

大功告成,在导航栏尝试输入一些关键词,看看效果吧!

当然这样的搜索功能是非常简略的,难以满足一些复杂的搜索需求。编写一个搜索引擎是一个大工程,好在 django-haystack 这款第三方 app 为我们完成了全部工作。使用它我们可以实现更加复杂的搜索功能,比如全文检索、按搜索相关度排序、关键字高亮等等类似于百度搜索的功能,功能十分强大。当然其使用也会复杂一些,下一篇教程将向大家介绍 django-haystack 结合 Elasticsearch 搜索引擎的使用方法。


更多相关文章

  1. udp数据报从网卡驱动到用户空间流程总结
  2. Go:fmt.Scanln在控制台获取用户输入的值
  3. 用户添加,修改,删除
  4. Linux 命令 su 和 sudo 的区别?
  5. django中的session实现
  6. 用户表、商品表、订单表
  7. 用户登录及注销
  8. Oracle的用户权限及其管理操作
  9. 使用面向对象方法实现用户信息增删改查

随机推荐

  1. Android单元测试学习记录
  2. Android Dialog风格弹出框的Activity
  3. Android TV listView焦点平滑移动
  4. Android休眠唤醒驱动流程分析
  5. Android Bitmap与String互转
  6. d
  7. Android:自定义view实现动画
  8. Android 数据库 短信 监听
  9. android唤醒屏幕--保持屏幕唤醒-Reprinte
  10. Android如果对APK进行加密,提高反编译难度