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

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

作者: 猴哥爱读书 | 来源:发表于2018-04-09 09:30 被阅读141次
    题图:by click_vision from Instagram

    前面的文章已经把模板、模型、视图、表单等知识点逐一讲解,大家已经熟悉它们具体用法。但如何将其串联起来还一筹莫展。本篇文章分享我之前做过的一个小项目,帮助大家抹开这一层迷雾。

    1 想做什么?

    我分享的项目是一个社工库查询系统。大家不要一拿到源码,就直接去阅读。建议先思考下,如果让我来设计社工库查询系统,我要如何实现?

    我就先阐述我思考的内容。既然项目是一个查询系统,那么重点在于查询。众所周知,查询数据则是执行 SQL 语句来从数据库中获取数据。SQL 查询语句一般使用表中的字段作为查询条件。哪些能作为查询条件呢?先让我们来看看数据库表是怎么定义的?

    2 数据库表

    数据库中只有一个表,名为 Socialusers。它的创建语句是:

    Create table if not exists `SocialUsers` (
         `id` INTEGER PRIMARY KEY,
         `username` varchar(64),
         `password` varchar(64),
         `chineseName` varchar(64) ,
         `email` varchar(64) ,
         `QQ` varchar(15) ,
         `weibo` varchar(300),
         `identity_number` varchar(25),
         `cell_phone` varchar(20),
         `ip_address` varchar(100),
         `college` varchar(60),
         `living_place` varchar(200),
         `source` varchar(50),
         `remarks` varchar(400)
         );
    

    表中一共有 13 个字段,其中有 9 个字段的内容属于敏感字段,涉及到个人账号安全问题。因此,我将这 9 个字段,分别是 username、password、chineseName、email、QQ、identity_number、cell_phone、college、source 作为查询条件

    那么系统最终的效果是根据查询条件和用户输入的内容来查询数据。如果数据库匹配到数据,就通过表格形式打印数据。反之则提醒用户查询不到数据(查询不到数据应该值得庆幸的,说明你的账号数据没有被泄露)。

    我将查询条件以下拉框的形式显示,让用户可以自行选择查询条件。查询内容以文章输入框展示,提供用户输入数据的接口。到这里可以回答之前的想要做什么的问题了。我们最终要实现的页面效果如下:


    点击查看大图

    3 模型建立

    数据库已经有了表,我直接使用 Django 自带工具生成 Socialusers 模型。这一步就省略不讲,如果你对这步操作不是很熟悉,可以阅读《Django 学习笔记之使用旧数据库》的内容。

    最终生成的模型如下:

    class Socialusers(models.Model):
        id = models.IntegerField(blank=True, primary_key=True)
        username = models.CharField(max_length=64, blank=True, null=True)
        password = models.CharField(max_length=64, blank=True, null=True)
        # Field name made lowercase.
        chinesename = models.CharField(db_column='chineseName', max_length=64, blank=True, null=True)  
        email = models.CharField(max_length=64, blank=True, null=True)
        # Field name made lowercase.
        qq = models.CharField(db_column='QQ', max_length=15, blank=True, null=True)  
        weibo = models.CharField(max_length=300, blank=True, null=True)
        identity_number = models.CharField(max_length=25, blank=True, null=True)
        cell_phone = models.CharField(max_length=20, blank=True, null=True)
        ip_address = models.CharField(max_length=100, blank=True, null=True)
        college = models.CharField(max_length=60, blank=True, null=True)
        living_place = models.CharField(max_length=200, blank=True, null=True)
        source = models.CharField(max_length=50, blank=True, null=True)
        remarks = models.CharField(max_length=400, blank=True, null=True)
    
        class Meta:
            managed = True
            db_table = 'SocialUsers'
    

    注意下 chinesename 和 qq 这两个属性。我们在数据库中的定义是 chineseName 和 QQ。而 Django 在生成的模型时,自动将大写转为化小写。因此,当我们在使用 Socialusers 这两个属性时,要注意它们的定义已经改变,属性的定义全是小写的。

    4 表单实现

    表单的实现由两种方式:一种是根据 model 生成 Form,另一种是自定义 Form。我分别把这两种方式实现。你可以对比下这两种写法的差异,以及如何给表单指定 bootstrap CSS 样式的。

    4.1 根据 model 生成 Form

    在 app 目录下新建文件夹 forms 以及文件 forms.py 。forms.py 主要存放表单的定义,实现代码如下:

    # forms.py 
    CONDITION_CHOICES = (
        ('username', '用户名'),
        ('password', '密码'),
        ('chineseName', '姓名'),
        ('email', '邮箱'),
        ('QQ', 'QQ'),
        ('identity_number', '身份证'),
        ('cell_phone', '电话'),
        ('college', '大学'),
        ('source', '来源'),
    )
    
    class QueryUserForm(forms.Form):
        condition = forms.CharField(  # 也可以定义为 ChoiceField
            max_length=20,
            widget=forms.Select(choices=CONDITION_CHOICES,
                                attrs={'class':"form-control",
                                        'title':"query condition",
                                        'name':'condition',
                                        }),
            localize=('username', '用户名')
        )
    
        queryContent = forms.CharField(
            max_length=100,
            widget=forms.TextInput(attrs={'class': 'form-control is-invalid',
                                          'name': 'queryContent',
                                          'placeholder': '请输入需要要查询的内容...'
                                          }),
            error_messages={'required': '查询内容不能为空 !'}
        )
    

    其中, widget 是指定字段呈现样式,如 condition 被指定呈现下拉框 Select;localize 是设置初始化值;error_messages 是错误提示形式。attrs 是为呈现的组件指定一些属性,如 CSS 样式、name 等。这部分内容,后面的文章会做详细讲解。

    4.2 自定义 Form

    为了更好区分模型,我在 models.py 中新建一个模型来代替之前的 Socialusers 模型。

    # models.py 
    # 用于表单查询的 model
    CONDITION_CHOICES = (
        ('username', '用户名'),
        ('password', '密码'),
        ('chineseName', '姓名'),
        ('email', '邮箱'),
        ('QQ', 'QQ'),
        ('identity_number', '身份证'),
        ('cell_phone', '电话'),
        ('college', '大学'),
        ('source', '来源'),
    )
    
    class QueryUser(models.Model):
        condition = models.CharField(max_length=20, choices=CONDITION_CHOICES)
        queryContent = models.CharField(max_length=100)
    
        def __str__(self):    # __unicode__ on Python 2
            return self.condition
    

    Form 的实现代码如下:

    # forms.py 
    class QueryUserForm(ModelForm):
        class Meta:
            model = QueryUser
            fields = ['condition', 'queryContent', ]
            # 指定呈现样式字段、指定 CSS 样式
            widgets = {
                'condition': Select(attrs={'class':"form-control",
                                        'title':"query condition",
                                        'name':'condition',
                                        }),
                'queryContent':TextInput(attrs={'class': 'form-control is-invalid',
                                          'name': 'queryContent',
                                          'placeholder': '请输入需要要查询的内容...'
                                          })
            }
    
            localized = {
                'condition':('username', '用户名'),
                'queryContent':123
            }
    
            # 自定义错误信息
            error_messages = {
                'queryContent':{
                    'required': '查询内容不能为空 !',
                }
            }
    

    各个字段的含义跟第一种实现方式类似,我就不重复说明。

    5 模板创建

    我创建名为 templates 文件夹来存放 HTML 文件。其中 index.html 是主页面,也是我们查询数据的页面。因为我前端框架使用的是 bootstrap,所以需要加载一些库。我为了满足在电脑无网络的状态也能使用的需求。我将其 bootstrap 所用到的库到打包到 static 目录下。

    代码比较多,我只把重点内容贴出来。详细代码可以到 Github 网站上查看完整代码

    {% load staticfiles %}
    <!DOCTYPE html>
    <html>
    <body>
        <div class="container" id="container">
            <div id="page-header">
                <h1 class="text-center"> 社工库查询系统 </h1>
            </div>
    
            <div class="row">
            <form action="" method="GET" class="form-horizontal" role="form">
                <div id="checkbox" class="text-center">
                    <label class="checkbox-inline text-success">默认采用完整匹配</label>
                </div>
    
                <div class="col-md-10 col-md-offset-1">
                    <div class="col-md-2 col-md-offset-0">
                        {{ form.condition }}
                        {% comment %}
                        {{ form.condition }} 在 html 中将被渲染成以下代码
                        <select name='condition' title="query condition" class="form-control">
                            <option >用户名</option>
                            <option>密码</option>
                            <option>姓名</option>
                            <option>邮箱</option>
                            <option>QQ</option>
                            <option>身份证</option>
                            <option>电话</option>
                            <option>大学</option>
                            <option>来源</option>
                        </select>
                        {% endcomment %}
                    </div>
    
                    <div class="input-group col-md-10 col-md-offset-1">
                        {{ form.queryContent.field.errors }}
                        {{ form.queryContent }}
    
                        {% comment %}
                        {{ form.queryContent }} 在 html 中将被渲染成以下代码
                        <input type="text" class="form-control is-invalid" name="q" placeholder="请输入内容..." value="">
                        {% endcomment %}
    
                        <div class="input-group-btn">
                            <button type="submit" class="btn btn-primary" required >Search</button>
                            <div class="invalid-feedback">
                                Please provide a valid value.
                            </div>
                        </div>
                    </div>
                </div>
            </form>
            </div>
            <br>
        </div>
    </body>
    </html>
    

    在 html 代码中,我直接将 form 标签直接写出来,里面的 Select 和 Input 标签通过 Django Form 来填充。下拉框使用表单的 condition 属性,即 {{ form.condition }} 来填充 ,输入框也是使用 {{ form.queryContent }} 来填充。当它们渲染的时候,会自动被解析为 Select 和 input 控件。

    6 视图

    我设定是用户提交表单地址不改变。所以表单数据会被提交到原来的页面。因此,在视图的工作是拦截表单,并截取里面的内容。最后将查询结果返回给 HTML 页面。

    # views.py
    def index(request):
        templateView = 'index.html'
    
        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)
    
                # 查询数据...
                
                return render(request, templateView, {'form': form})
            # 直接访问主页, 显示的内容
            else:
                return render(request, templateView, {'form': form})
    

    系统的基本框架已经搭建差不多。因为文章篇幅关系,一部分内容下篇文章讲解。下篇文章主要是如何查询数据、如何根据查询结果显示不同内容、如何将数据呈现出来。

    7 写在最后

    我新建一个 Python Web 学习交流 QQ 群,群号:701534112。欢迎大家加群,一起交流,一起学习,一起进步。


    Python Web 学习交流群

    往前 Django 学习笔记文章
    Django 学习笔记之环境搭建
    Django 学习笔记之初始
    Django 学习笔记之视图与URL配置
    Django 学习笔记之模板
    Django 学习笔记之模型(上)
    Django 学习笔记之模型(下)
    Django 学习笔记之后台管理
    Django 学习笔记之模型表单
    Django 学习笔记之使用旧数据库


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

    相关文章

      网友评论

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

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