本节实现效果:
在上一小节中我们实现了账号管理这个功能,今天我们实现上一小节中遗留的几个点,分别是条件筛选与搜索和翻页处理。
条件筛选与搜索:
条件筛选的实质就是通过给予条件给数据库让数据库传递给我们需要的数据,展示客户需要查看的数据。
例如我们选择要查询手机号为15355556666,id值为7的数据,那我们就可以这么写入我们的条件
models.PrettyNum.objects.filter(mobile="15355556666",id=7)
这样数据库就能给我们返回符合条件的全部数据。
Django为我们提供了一些条件筛选的方法:
对于整数
models.PrettyNum.objects.filter(price=100) 价格等于100
models.PrettyNum.objects.filter(price__gt=100) 价格大于100
models.PrettyNum.objects.filter(price__gte=100) 价格大于等于100
models.PrettyNum.objects.filter(price__lt=100) 价格小于100
models.PrettyNum.objects.filter(price__lte=100) 价格小于等于100
对于字符串
models.PrettyNum.objects.filter(mobile__contains="153") 包含135
models.PrettyNum.objects.filter(mobile__startswidth="153") 以135开头
models.PrettyNum.objects.filter(mobile__endswidth="153") 以135结尾
下面我介绍两种方式的查询手段:
手机号查询(表单提交获取表单内容)
我们选择需要实现这个需求:当我们输入手机号的部分数据的时候,数据库就会将包含这些数据的手机号给我们显示出来
我们在我们的输入框中输入135时,数据库就会只为我们展示包含135的数据。
那我们就根据这个思路开始实现我们的代码:
首先我们是想通过表单将我们的数据进行一个提交,我们可以将我们传入的数据以参数的形式返回到我们的后端,然后让后端将获取到的请求获取其中的参数信息,最后通过参数信息进行数据筛选,最后返回筛选后的数据。
我们在我们的pertty.html页面中创建一个表单,将其属性name的值query作为参数,然后让后端获取到这个query。
<div style="float: right; width: 300px">
<form method="get">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search for..." name="query">
<span class="input-group-btn">
<button class="btn btn-default" type="submit"><span class="glyphicon glyphicon-search"
aria-hidden="true"></span></button>
</span>
</div>
</form>
</div>
下面我们开始重新写我们的账号列表展示的这个组件的方法。
pretty.py
def pretty_list(request):
# 筛选条件字典
dict_data = {}
# 搜索
value = request.GET.get('query')
if value:
dict_data['mobile__contains'] = value
# order_by 将level从低到高排序
queryset = models.PrettyNum.objects.filter(**dict_data).order_by('level')
return render(request,'pretty_list.html',{'data_pretty_list':queryset})
这样我们的搜索条件即可完成。
等级筛选(a标签直接请求并传递参数)
我们在对手机号查询是通过输入进行搜索查询,现在我想要通过按钮直接点击即可将我想要的内容进行展示。
其实大家可以直接写这个内容,无非就是一个下拉框下面有我们需要查询的条件,但是如果说我们直接写的话如果出现很多条件,例如等级如果说有20条,那我们也不能写20个a标签。
其实这个问题也很好解决,我们在models.py对level这个字段进行编写的时候是使用了一个choiice进行一个映射选择。
我们可以直接通过类获取到这个数据然后将其传入到前端进行一个遍历即可。
pretty.html
{# 等级筛选 #}
<div style="float: right">
<div class="input-group">
<div class="btn-group">
<button type="button" class="btn btn-warning dropdown-toggle" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">等级筛选<span class="caret"></span></button>
<ul class="dropdown-menu">
{% for data in level_list %}
<li><a href="?level={{ data.0 }}">{{ data.1 }}</a></li>
{% endfor %}
</ul>
</div>
</div>
</div>
其中data就是这个大元组中的其中一个小元组,data.0就是前面的数字,而data.1就是后面的等级,我们在点击这个a标签时,他会发送一个请求给到我们的后端,然后我们的后端仅需获取里面的参数level,将其作为条件进行筛选,最后将筛选后的数据传递给我们的前端。
pretty.py
def pretty_list(request):
# 筛选条件字典
dict_data = {}
# 搜索
value = request.GET.get('query')
if value:
dict_data['mobile__contains'] = value
value = request.GET.get('level')
if value:
dict_data['level__contains'] = value
# 统计数据表当中有多少条数据
queryset = models.PrettyNum.objects.filter(**dict_data).order_by('level')
# 筛选等级
level_list = models.PrettyNum.level_choice
return render(request,'pretty_list.html',{'data_pretty_list':queryset ,'level_list':level_list})
以上就是我们的条件筛选板块就完成了。
翻页处理:
为了便于我们进行观察翻页处理,我们往数据库中多添加一些数据。
需求:
1. 我只希望它一页给我展示10条数据
2. 我只希望它只给我展示以当前页面为基准,同时展示前三页和后三页,随着页面的变化这些页面选择也会发送变化
3. 我需要有一个首页和尾页标签,通过点击即可跳转到首页和尾页
4. 我需要有一个上一页和下一个标签,通过点击即可跳转到上一页和下一页
5. 最后我需要实现一个条件搜索,通过指定页面即可跳转到该条件下的页面
需求1:一页展示10条数据
我们通过数据表进行查询的数据实质上是一个列表,列表里面是我们的一条数据,然后这些数据是由一个一个键值对组成,对于列表我们要进行一个数据划分最好的方式就是切片。可以想一想我们切片的起点是不是应该为 (当前页面 - 1) * 展示条数,而我们的切片终点为 当前页面 * 展示条数,这个可以带值进行计算这里就不在赘述。
# 翻页
page = int(request.GET.get("page", 1))
# 当前一页展示10条信息
page_size = 10
# 开始切片
start = (page - 1) * page_size
# 结束切片
end = page * page_size
需求2:以当前页面为基准,同时展示前三页和后三页
例如我以7为基准,然后 它会给我展示4,5,6页,8,9,10页。然后我们将4-10页分别展示即可。因此我们可以通过这样的方式进行计算,当前页面-3为起点,当前页面+3为终点,然后遍历即可。有细心的小伙伴会发现这个方法其实并不完美,如果说当前页面为1,那么我们在-3后它的起点是-2,这样并不符合逻辑。如果说当前页面为最后一个,那么我们在+3后它的终点会超过我们最后一页的范围,这样也不符合逻辑,还有一种情况就是如果数据并没有7条数据,那么这么计算也会出现问题,因此我们需要对这样特殊的位置进行一个处理。
对于最前面三页:我们可以直接将起点设置为1,终点则为 2 * 3 + 1。
对于最后面三页:我们可以将起点设置为总页数 - 2 * 3,终点为总页数。
如果数据并没有7条数据,那么我们直接将起点设置为1,终点为总页数即可。
# 统计数据表当中有多少条数据
total_count = models.PrettyNum.objects.filter(**dict_data).order_by("level").count()
data_pretty_list = models.PrettyNum.objects.filter(**dict_data).order_by("level")[start: end]
# 根据数据表当中的数据条数以及分页的数据条数计算分多少页
total_page_count, div = divmod(total_count, page_size)
if div:
total_page_count += 1
# 计算出当前页展示的前三页和后三页
plus = 3
# 如果当前数据表数据小于7
if total_page_count <= 2 * plus + 1:
start_page = 1
end_page = total_page_count
else:
# 当前选中的页小于3的时候(最小)
if page <= plus:
start_page = 1
end_page = 2 * plus + 1
else:
# 当前页+3大于总页数 总页数21 22 23 24
if (page + plus) > total_page_count:
start_page = total_page_count - 2 * plus
end_page = total_page_count
else:
# 开始的页面
start_page = page - plus
end_page = page + plus
# 页码列表
page_str_list = []
for page_num in range(start_page, end_page+1):
if page_num == page:
page_ele = f'<li class="active"><a href="?page={page_num}">{page_num}</a></li>'
else:
page_ele = f'<li><a href="?page={page_num}">{page_num}</a></li>'
page_str_list.append(page_ele)
需求3:首页和尾页
对于首页和尾页的处理非常简单,我相信大家一看就能明白,就不多赘述了。
# 首页
page_str_list.append(f'<li class="active"><a href="?page={1}">首页</a></li>')
# 尾页
page_str_list.append(f'<li class="active"><a href="?page={total_page_count}">尾页</a></li>')
需求4:上一页和下一页
上一页无非就是在这一页的基础上做一个-1的操作,但是我们有一个点需要注意一下,就是我们在对于第一页进行操作的时候它的上一页是没有的,因此我们需要对当前页面为1的时候做一个禁止它点击操作。
下一页无非就是在这一页的基础上做一个+1的操作,但是我们有一个点需要注意一下,就是我们在对于最后一页进行操作的时候它的下一页是没有的,因此我们需要对当前页面为最后一页的时候做一个禁止它点击操作。
# 上一页(当前页-1)
if page > 1:
page_str_list.append(f'<li class="active"><a href="?page={page - 1}">上一页</a></li>')
else:
page_str_list.append(f'<li class="active"><a href="?page={1}" style="pointer-events:none;">上一页</a></li>')
# 下一页(当前页+1)
if page < total_page_count:
page_str_list.append(f'<li class="active"><a href="?page={page + 1}">下一页</a></li>')
else:
page_str_list.append(f'<li class="active"><a href="?page={1}" style="pointer-events:none;">下一页</a></li>')
需求5:页面跳转
页面跳转的思想在刚刚的条件筛选那边已经说过了,这边就直接给出代码,大家可以对比看一下。
serch_string = """
<li>
<form method="get" style="float: left; margin-left: 1px">
<input type="text" class="form-control" placeholder="页码" name="page"
style="position: relative;float: left;display: inline-block;width: 70px">
<button type="submit" class="btn btn-info dropdown-toggle">跳转</button>
</form>
</li>
"""
page_str_list.append(serch_string)
最后我们将这个页面列表传递到前端页面中即可
# 用于将字符串数据转化为源代码格式
from django.utils.safestring import mark_safe
page_string = mark_safe(''.join(page_str_list))
return page_string
pretty.py:
# -------------------------账号管理----------------------------------------------
def pretty_list(request):
# 搜索
dict_data = {}
value = request.GET.get("query")
if value:
dict_data["mobile__contains"] = value
value = request.GET.get('level')
if value:
dict_data['level'] = value
# 翻页
page = int(request.GET.get("page", 1))
# 当前一页展示10条信息
page_size = 10
# 开始切片
start = (page - 1) * page_size
# 结束切片
end = page * page_size
level_list = models.PrettyNum.level_choice
# 统计数据表当中有多少条数据
total_count = models.PrettyNum.objects.filter(**dict_data).order_by("level").count()
data_pretty_list = models.PrettyNum.objects.filter(**dict_data).order_by("level")[start: end]
# 根据数据表当中的数据条数以及分页的数据条数计算分多少页
total_page_count, div = divmod(total_count, page_size)
if div:
total_page_count += 1
# 计算出当前页展示的前三页和后三页
plus = 3
# 如果当前数据表数据小于7
if total_page_count <= 2 * plus + 1:
start_page = 1
end_page = total_page_count
else:
# 当前选中的页小于3的时候(最小)
if page <= plus:
start_page = 1
end_page = 2 * plus + 1
else:
# 当前页+3大于总页数 总页数21 22 23 24
if (page + plus) > total_page_count:
start_page = total_page_count - 2 * plus
end_page = total_page_count
else:
# 开始的页面
start_page = page - plus
end_page = page + plus
# 页码列表
page_str_list = []
# 首页
page_str_list.append(f'<li class="active"><a href="?page={1}">首页</a></li>')
# 上一页(当前页-1)
if page > 1:
page_str_list.append(f'<li><a href="?page={page - 1}">上一页</a></li>')
else:
page_str_list.append(f'<li><a href="?page={1}" style="pointer-events:none;">上一页</a></li>')
for page_num in range(start_page, end_page + 1):
if page_num == page:
page_ele = f'<li class="active"><a href="?page={page_num}">{page_num}</a></li>'
else:
page_ele = f'<li><a href="?page={page_num}">{page_num}</a></li>'
page_str_list.append(page_ele)
# 下一页(当前页+1)
if page < total_page_count:
page_str_list.append(f'<li><a href="?page={page + 1}">下一页</a></li>')
else:
page_str_list.append(f'<li><a href="?page={1}" style="pointer-events:none;">下一页</a></li>')
# 尾页
page_str_list.append(f'<li><a href="?page={total_page_count}">尾页</a></li>')
# 将字符串传递到源代码
page_string = mark_safe("".join(page_str_list))
return render(request, "pretty_list.html", {"data_pretty_list": data_pretty_list, "page_string": page_string,'level_list':level_list})
pretty_list.html:
{% extends 'layout.html' %}
{% block content %}
<div class="container">
<div style="margin-bottom: 10px">
{# target="_blank" 重新打开一个页面 #}
<a href="/pretty/add/" class="btn btn-success">
<span class="glyphicon glyphicon-plus" aria-hidden="true"></span> 新建账号</a>
</div>
{#搜索按钮#}
<div style="float: right; width: 300px">
<form method="get">
<div class="input-group">
<input type="text" class="form-control" placeholder="Search for..." name="query">
<span class="input-group-btn">
<button class="btn btn-default" type="submit"><span class="glyphicon glyphicon-search"
aria-hidden="true"></span></button>
</span>
</div>
</form>
</div>
{# 等级筛选 #}
<div style="float: right">
<div class="input-group">
<div class="btn-group">
<button type="button" class="btn btn-warning dropdown-toggle" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">等级筛选<span class="caret"></span></button>
<ul class="dropdown-menu">
{% for data in level_list %}
<li><a href="?level={{ data.0 }}">{{ data.1 }}</a></li>
{% endfor %}
</ul>
</div>
</div>
</div>
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title"><span class="glyphicon glyphicon-th-list" aria-hidden="true"></span> 账号列表</h3>
</div>
<div class="panel-body">
<table class="table">
<thead>
<tr>
<th>账号ID</th>
<th>号码</th>
<th>价格</th>
<th>级别</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for data in data_pretty_list %}
<tr>
<td>{{ data.id }}</td>
<td>{{ data.mobile }}</td>
<td>{{ data.price }}</td>
<td>{{ data.get_level_display }}</td>
<td>{{ data.get_status_display }}</td>
<td>
{# <a href="/user/delete/?nid={{ data.id }}"><span class="glyphicon glyphicon-trash"#}
{# aria-hidden="true"#}
{# style="color: red"></span></a>#}
<a href="/pretty/{{ data.id }}/delete/"><span class="glyphicon glyphicon-trash"
aria-hidden="true"
style="color: red"></span></a>
<span> </span>
<a href="/pretty/{{ data.id }}/modify"><span class="glyphicon glyphicon-new-window"
aria-hidden="true"
style="color: #2aabd2"></span></a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<ul class="pagination">
{{ page_string }}
</ul>
</div>
{% endblock %}
以上就是本次条件筛选和搜索的全部内容,如若有不明白或者有错误的地方,可以后台私信,谢谢大家。