![](https://img.haomeiwen.com/i7931281/197c83063923875c.jpg)
上篇文章已经完成框架搭建,本文接着上篇的内容继续讲解。本片主要的说三点内容,分别是:根据条件查询数据、根据查询结果显示不同内容、将查询数据填充到页面上。
1 逻辑优化
在上篇文章,我在原来的 url 地址中处理用户提交的表单数据。Url 值改变了,但是页面没有刷新。同时,表单数据没有进行分类。这会导致用户不管提交什么数据,页面就呈现什么数据。
而正常的逻辑应该是这样。如果用户访问的是首页,那么不需要填充任何数据以及展示提示框。
![](https://img.haomeiwen.com/i7931281/1a5a4a5a24f432fb.png)
如果用户提交了表单数据,但是数据库中没有查询到数据,则提醒下用户没有查询到相关数据。
![](https://img.haomeiwen.com/i7931281/ab96aac8d53a2cda.png)
如果用户提交了表单数据,数据库也能查询到数据。页面需要提醒用户查询到数据,并将查询结果展示出来。
![](https://img.haomeiwen.com/i7931281/946d69af8dc781d6.png)
为了解决这个问题,我通过定义一个变量 countNum 来区分。
2根据查询结果显示不同内容
2.1 视图改造
按照解决方案,我们需要对 V 层进行改造。定义全局变量 countNum,初始化为 -1。如果用户访问的是首页,就直接返回。如果用户提交表单数据,数据库查询不到数据。则将 countNum 赋值为 0 ,然后返回。如果用户提交表单数据,数据库查询不到数据,就返回数据总条。
# views.py
def index(request):
templateView = 'index.html'
countNum = -1
keywords = ''
if request.method == 'GET':
form = QueryUserForm(request.GET)
# 验证表单
if form.is_valid():
# 过滤需要的数据
condition = form.cleaned_data['condition']
keywords = form.cleaned_data['queryContent']
print('condition == ' + condition)
print('keywords == ' + keywords)
countNum = 0
# 查询结果
# 假设经过查询, 一共获取到 3 条数据
countNum = 3
if countNum != 0:
return render(request, templateView, {
'countNum': countNum,
'keywords': keywords,
'form': form,
})
# 查询不到数据, 显示没有数据的浮窗
if countNum == 0:
return render(request, templateView, {
'countNum': countNum,
'keywords': keywords,
'form': form,
})
# 直接访问主页, 显示的内容
else:
return render(request, templateView, {'countNum': countNum, 'form': form})
2.2 模板改造
T 层(模板)需要根据 V 层(视图)透传过来的 countNum 的值进行判断,然后渲染相应的内容。
# index.html
<!DOCTYPE html>
<html>
<body>
<div class="container" id="container">
<!-- 前面代码不变 -->
{% if countNum == -1 %}
<!-- 显示首页内容, 不需要做处理 -->
{% else %}
<!-- 查询不到数据, 提醒用户更换 关键词或者类型 -->
{% if countNum == 0 %}
<div class="alert alert-warning alert-dismissible col-md-10 col-md-offset-1" role="alert">
<button type="button" class="close" data-dismiss="alert">
<span aria-hidden="true">×</span>
<span class="sr-only">Close</span></button>
找不到与<b> {{ keywords }} </b>相关的结果。请更换其他<b> 关键词或类型 </b>试试。</div></div>
{% else %}
<!-- 显示总数以及查询耗时
打印表格、说明头部行、查询到的数据-->
<div class="row">
<div class="alert alert-success alert-dismissible col-md-10 col-md-offset-1" role="alert">
<button type="button" class="close" data-dismiss="alert">
<span aria-hidden="true">×</span>
<span class="sr-only">Close</span></button>
找到与<b>  {{ keywords }}  </b>相关的结果 {{ countNum }} 个。用时 {{ time }} 秒。</div>
<div class="table-responsive col-md-12">
<table class="table table-striped table-hover">
<tr>
<th class="text-center">用户名</th>
<th class="text-center">密码</th>
<th class="text-center">姓名</th>
<th class="text-center">邮箱</th>
<th class="text-center">QQ 号码</th>
<th class="text-center">数据来源</th>
</tr>
<!-- 填充查询到的数据 -->
</table></div></div>
{% endif %}
{% endif %}
</div>
</body>
</html>
3 根据条件查询数据
模型层主要跟数据库打交道, 数据库存储数据的地方。所以查询数据内容其实是模型知识地运用。
考虑到数据库中可能存在多条关键字(queryContent)相关的数据,所以需要使用 filter() 来匹配。我使用的匹配模式是精确匹配,所以无须使用正则表达式来匹配。直接把关键字作为模型过滤条件就可以了,实现代码如下:
# 把 Socialusers 的 username 属性作为 condition 来查询数据。
# 查询内容是用户输入的内容 queryContent
user_list = Socialusers.objects.filter(username=keywords)
# 获取总条数
countNum = user_list.count()
condition 记录用户选择下拉框的条目值。该变量的值决定模型 Socialusers 要使用哪个属性来查询。由于 python 没有 switch 语句,只能写多个 elif 来处理多个条件。那么代码可以这么实现:
# views.py
def index(request):
templateView = 'index.html'
countNum = -1
keywords = ''
time = 0
if request.method == 'GET':
form = QueryUserForm(request.GET)
# 验证表单
if form.is_valid():
# 过滤需要的数据
condition = form.cleaned_data['condition']
keywords = form.cleaned_data['queryContent']
print('condition == ' + condition)
print('keywords == ' + keywords)
countNum = 0
# 查询结果
if condition == 'username':
user_list = Socialusers.objects.filter(username=keywords)
countNum = user_list.count()
# 获取查询耗时
time = (connection.queries)[0].get('time')
print('user_list size=== ', user_list.count())
print('time === ', time)
# 显示分页操作, 每页显示 20 条
paginator = Paginator(user_list, 20)
page = request.GET.get('page')
try:
users = paginator.page(page)
except PageNotAnInteger:
# 如果请求的页数不是整数,返回第一页。
users = paginator.page(1)
except EmptyPage:
# 如果请求的页数不在合法的页数范围内,返回结果的最后一页。
users = paginator.page(paginator.num_pages)
return render(request, templateView, {
'countNum': countNum,
'condition': condition,
'keywords': keywords,
'form': form,
'users': users,
'time': time,
})
elif condition == 'password':
# 后面的代码逻辑跟前面类似, 只不过 filer() 的内容改变了。
# 查询不到数据, 显示没有数据的浮窗
if countNum == 0:
return render(request, templateView, {
'countNum': countNum,
'keywords': keywords,
'form': form,
})
# 直接访问主页, 显示的内容
else:
return render(request, templateView, {'countNum': countNum, 'form': form})
代码中使用到了分页 Paginator,这部分后面会继续讲解。
4 填充数据
最后一步工作就是在模板中填充查询到的数据。因为我们在视图中将查询到 user_list 集合传递给模板。这里要注意的是,user_list 其实是一个查询集 QuerySet,不是真正意义上的列表,只不过命名为列表而已。在模板中,使用一个 for 循环逐一解析每个模型的值,就能完成数据填充工作。
# index.html
<!-- 填充查询到的数据 -->
# 在下面的注释下面,打印查询到的数据
{% for user in users %}
<tr>
<td class="text-center">{{ user.username }}</td>
<td class="text-center">{{ user.password }}</td>
<td class="text-center">{{ user.chinesename }}</td>
<td class="text-center">{{ user.email }}</td>
<td class="text-center">{{ user.qq }}</td>
<td class="text-center">{{ user.source }}</td>
</tr>
{% endfor %}
第一个实战项目到这里就结束了。主要目的是让大家明白如何将模型、表单、模板、视图串联起来。后面的文章会讲解高级用法以及前面遗漏的细节内容。
项目的源代码下载地址:点击这里
5 写在最后
我新建一个 Python Web 学习交流 QQ 群,群号:701534112。欢迎大家加群,一起交流,一起学习,一起进步。
![](https://img.haomeiwen.com/i7931281/e167b584ec334644.png)
往前 Django 学习笔记文章
Django 学习笔记之环境搭建
Django 学习笔记之初始
Django 学习笔记之视图与URL配置
Django 学习笔记之模板
Django 学习笔记之模型(上)
Django 学习笔记之模型(下)
Django 学习笔记之后台管理
Django 学习笔记之模型表单
Django 学习笔记之使用旧数据库
Django 实战1:搭建属于自己社工查询系统(上)
本文原创发布于微信公众号「极客猴」,欢迎关注第一时间获取更多原创分享
网友评论