【Django2.0学习笔记】45.站内简单搜索

45、站内简单搜索

1、搜索功能作用

  • 1、让更多博客内容被挖掘出来
  • 2、用户体验更好
    在这里插入图片描述

2、搜索功能实现方法

  • 1、用户提交搜索请求(参数搜索关键字)
  • 2、根据关键字查找博客标题和内容(通过filter筛选方式)
    在这里插入图片描述

我们先要实现在页面加一个搜索框,加在导航栏的右侧,那这就要加到最底层的模板,
查看Bootstrap,在“组件”——“导航条”,
在这里插入图片描述
修改base.html如下:
在这里插入图片描述
刷新页面
在这里插入图片描述
这个submit按钮有点多余,我们可以改个样式,查看Bootstrap组件 图标
在这里插入图片描述
修改base.html如下:
在这里插入图片描述

刷新页面:
在这里插入图片描述
然后修改一下样式,让搜索的图标放到搜索框里面来,修改base.css如下:
在这里插入图片描述
刷新页面:
在这里插入图片描述
接着我们回到base.html这里,我们点击提交按钮,会把表单这些东西给提交上去,也就是input标签里面的内容。这里我们设置提交参数名称name为wd,这样提交的内容就会提交给后端,那么后端得有一个处理方法给这个form去提交,所以我们需要给后端加一个处理链接和方法。
在这里插入图片描述
首先我们给后端加一个处理方法,这个是全局的,所以我们在mysite/views.py中进行添加:
在这里插入图片描述
然后配置路由,在mysite/urls.py中:
在这里插入图片描述
这样,有了处理方法和路由之后,我们就有了对应的处理方法可以处理前端页面提交的这个请求。那么现在我们给这个请求指定一个路径让它提交,用action参数来指定,修改base.html如下:
在这里插入图片描述
接着我们回到处理方法mysite/views.py对search方法进行编写:
在这里插入图片描述

def search(request):
	search_word = request.GET.get('wd', '')	# 获取到wd这个参数
	search_blogs = Blog.objects.filter(title__icontains=search_word) # = 全部匹配;__contains= 部分匹配,区分大小写;__icontains= 忽略大小写
	
	context = {}
	context['search_word'] = search_word
	context['search_blogs'] = search_blogs
	return render(request, 'search.html', context) # 通过render渲染出来,具体渲染页面为search.html,传递的参数是个字典context

接着我们创建下模板页面search.html,这是全局的,我们放到templates目录下:

<!-- C:\Users\12482\Desktop\py_learn\Django2.0_chapter46\mysite_env\mysite\templates\search.html -->
{% extends 'base.html' %}

{% block title %}
	我的网站 | 搜索
{% endblock %}

{% block header_extends %}
{% endblock %}

{% block nav_home_active %}active{% endblock %}

{% block content %}
    {{ search_word }}
    {% for blog in search_blogs %}
    	{{ blog.title }}
    {% empty %}
    	<p>搜索不到任何内容</p>
    {% endfor %}
{% endblock %}

刷新页面,搜索“内容”“for”
在这里插入图片描述
在这里插入图片描述
这样,我们搜索的核心基本功能已经实现了,接下来我们完善html页面

3、搜索规则

  • 1、部分匹配(只要标题或内容存在搜索内容即可)
  • 2、多个关键字可以用空格隔开(Q方法实现复杂逻辑)
  • 3、搜索结果分页(下一页和上一页)
  • 对TextField长文本字段进行部分匹配相对比较慢,建议不对TextField长文本字段搜索
    在这里插入图片描述

先修改views.py如下:
在这里插入图片描述
修改search.html如下:
在这里插入图片描述

<!-- C:\Users\12482\Desktop\py_learn\Django2.0_chapter46\mysite_env\mysite\templates\search.html -->
{% extends 'base.html' %}

{% block title %}
	我的网站 | 搜索
{% endblock %}

{% block header_extends %}
{% endblock %}

{% block nav_home_active %}active{% endblock %}

{% block content %}
	<div class="container">	
		<div class="row">
			<div class="col-md-8 col-md-offset-2">	
				{% if search_word == '' %}
					<h3>你没有搜索任何内容。</h3>
					<p>你可以尝试输入点什么东西,例如:Django</p>
				{% else %}
					<h3>搜索“{{ search_word }}”,找到{{ search_blogs_count }}个结果</h3>
					<hr>
					{% for blog in search_blogs %}
						<a href="{% url 'blog_detail' blog.pk %}">
							<h4>{{ blog.title }}</h4>
						</a>
						<p>{{ blog.content | striptags | truncatechars_html:100 }}</p>
					{% empty %}
						<p>没有找到任何东西,换个关键词试试吧</p>
					{% endfor %}
				{% endif %}
			</div>
		</div>
	</div>
{% endblock %}

刷新页面
在这里插入图片描述
在这里插入图片描述
我们可以看到如果搜索到的内容比较多的话,显示出来就比较长,我们可以做一个简单的分页(参考blog里面的views.py里面的分页代码)修改views.py如下:
在这里插入图片描述
修改search.html如下:
在这里插入图片描述
刷新页面
在这里插入图片描述

这样,我们就实现了分页功能。现在我们拓展下搜索规则,
以空格分开的搜索关键词是并列的关系,用filter不能直接实现筛选并列关键词,如果用逗号写多个筛选条件,逗号是and逻辑,表示同时满足,而我们空格分隔关键词想要的是or逻辑关系,这里django有实现的方法,查看官方文档
在这里插入图片描述
在这里插入图片描述
修改views.py如下(对应的将search.html里面面所有的search_word全部替换成search_words)
在这里插入图片描述

# 搜索框对应的处理方法
def search(request):
	search_words = request.GET.get('wd', '').strip()	# 获取到wd这个参数
	# 分词:按空格 & | ~
	condition = None
	for word in search_words.split(' '):
		if condition is None:
			condition = Q(title__icontains=word)
		else:
			condition = condition | Q(title__icontains=word)

	search_blogs = []
	if condition is not None:
		# 筛选:搜索	
		# search_blogs = Blog.objects.filter(title__icontains=search_words) # = 全部匹配;__contains= 部分匹配,区分大小写;__icontains= 忽略大小写
		search_blogs = Blog.objects.filter(condition)

	# 分页
	paginator = Paginator(search_blogs, 20)	# 每多少项作为一页
	page_num = request.GET.get('page', 1)	# 获取页码参数(GET请求)。# 看有没有‘page’这个属性,如果没有,则默认给1
	page_of_blogs = paginator.get_page(page_num)

	context = {}
	context['search_words'] = search_words
	context['search_blogs_count'] = search_blogs.count()
	# context['search_blogs'] = search_blogs
	context['page_of_blogs'] = page_of_blogs
	return render(request, 'search.html', context) # 通过render渲染出来,具体渲染页面为search.html,传递的参数是个字典context

templates/search.html:

<!-- C:\Users\12482\Desktop\py_learn\Django2.0_chapter46\mysite_env\mysite\templates\search.html -->
{% extends 'base.html' %}

{% block title %}
	我的网站 | 搜索
{% endblock %}

{% block header_extends %}
{% endblock %}

{% block nav_home_active %}active{% endblock %}

{% block content %}
	<div class="container">	
		<div class="row">
			<div class="col-md-8 col-md-offset-2">	
				{% if search_words == '' %}
					<h3>你没有搜索任何内容。</h3>
					<p>你可以尝试输入点什么东西,例如:Django</p>
				{% else %}
					<h3>搜索“{{ search_words }}”,找到{{ search_blogs_count }}个结果</h3>
					<hr>
					{% for blog in page_of_blogs %}
						<a href="{% url 'blog_detail' blog.pk %}">
							<h4>{{ blog.title }}</h4>
						</a>
						<p>{{ blog.content | striptags | truncatechars_html:100 }}</p>
					{% empty %}
						<p>没有找到任何东西,换个关键词试试吧</p>
					{% endfor %}
				{% endif %}
			</div>
		</div>
		<!-- 上一页 下一页 -->
		<div class="row" style="display: flex; justify-content: center;">
			{% if page_of_blogs.has_previous %}
				<a class="btn btn-default" href="{% url 'search' %}?wd={{ search_words }}&page={{page_of_blogs.previous_page_number}}">
					上一页
				</a>
			{% endif %}

			{% if page_of_blogs.has_next %}
				<a class="btn btn-default" href="{% url 'search' %}?wd={{ search_words }}&page={{page_of_blogs.next_page_number}}">
					下一页
				</a>
			{% endif %}
		</div>
	</div>
{% endblock %}

刷新页面,搜索“2 内容”,可以看到,成功搜索到标题包含“2”或“内容”的所有博客
在这里插入图片描述

至此,搜索关键字功能已经比较好的实现了

【遇到的小问题】:启动服务时显示出错“MySQLdb._exceptions.OperationalError: (2002, “Can’t connect to MySQL server on ‘localhost’ (10061)”)”
原因:MySQL连接断开了
解决办法:以管理员身份重新开一个cmd窗口,输入net start mysql启动mysql
在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值