美文网首页《Django By Example》码农的世界我爱编程
Django 实战1:搭建属于自己社工查询系统(下)

Django 实战1:搭建属于自己社工查询系统(下)

作者: 猴哥爱读书 | 来源:发表于2018-04-15 23:12 被阅读81次
题图:by thefolkpr0ject from Instagram

上篇文章已经完成框架搭建,本文接着上篇的内容继续讲解。本片主要的说三点内容,分别是:根据条件查询数据、根据查询结果显示不同内容、将查询数据填充到页面上。

1 逻辑优化

在上篇文章,我在原来的 url 地址中处理用户提交的表单数据。Url 值改变了,但是页面没有刷新。同时,表单数据没有进行分类。这会导致用户不管提交什么数据,页面就呈现什么数据。

而正常的逻辑应该是这样。如果用户访问的是首页,那么不需要填充任何数据以及展示提示框。


点击查看大图

如果用户提交了表单数据,但是数据库中没有查询到数据,则提醒下用户没有查询到相关数据。


点击查看大图

如果用户提交了表单数据,数据库也能查询到数据。页面需要提醒用户查询到数据,并将查询结果展示出来。


点击查看大图

为了解决这个问题,我通过定义一个变量 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">&times;</span>
                    <span class="sr-only">Close</span></button>
                    找不到与<b>&nbsp{{ keywords }}&nbsp</b>相关的结果。请更换其他<b>&nbsp关键词或类型&nbsp</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">&times;</span>
                    <span class="sr-only">Close</span></button>
                    找到与<b>&nbsp {{ keywords }} &nbsp</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。欢迎大家加群,一起交流,一起学习,一起进步。


Python Web 学习交流群

往前 Django 学习笔记文章
Django 学习笔记之环境搭建
Django 学习笔记之初始
Django 学习笔记之视图与URL配置
Django 学习笔记之模板
Django 学习笔记之模型(上)
Django 学习笔记之模型(下)
Django 学习笔记之后台管理
Django 学习笔记之模型表单
Django 学习笔记之使用旧数据库
Django 实战1:搭建属于自己社工查询系统(上)


本文原创发布于微信公众号「极客猴」,欢迎关注第一时间获取更多原创分享

相关文章

网友评论

本文标题:Django 实战1:搭建属于自己社工查询系统(下)

本文链接:https://www.haomeiwen.com/subject/lfxzhftx.html