假设我们制作了一个登陆页面,在输入完了用户名和密码点击了登陆按钮之后,将消息发往后端数据库。当验证失败的时候,再刷新整个登陆页面给用户提示错误。但是我们去其他网站注册新用户的时候,填写完用户名鼠标焦点刚刚移开就已经提示用户名已经存在了。但是此时整个页面并没有刷新。这个功能就是通过ajax异步请求实现的。所谓的异步请求,就是ajax可以只对页面的一部分内容进行更新操作,不需要加载全部页面。

    下面我们来设计一个登陆页面。设计的思路是:

1、页面有用户名和面膜的输入框,还有一个登陆按钮。
2、当输入一个用户名的之后,就马上将获取的用户名提交给后台数据库验证一下这个用户是否存在。如果不存在就弹出来一个告警框。(这个功能用ajax来实现)
3、如果用户存在就继续获取用户输入的密码,在验证该用户的密码是否正确。如果密码不正确就通过文字提示用户密码错误。如果用户密码也正确就把页面跳转到百度去。


首先,我们在app01应用下的views.py文件里编辑一个login()函数,实现我们的验证逻辑

/app01/views.py

# /usr/bin/env python
# coding:utf-8
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse
from app01 import models
def login(request):
    # 首先判断页面的请求方式
    #如果是POST就表明有表单内容要提交
    if request.method=='POST':
        #输入的获取用户名
        username=request.POST['username'].strip()
        #如果用户名能在数据库里找到
        if models.userinfo.objects.filter(user=username):
            #有用户再验证密码
            passwd=request.POST['passwd'].strip()
            db_passwd=models.userinfo.objects.filter(user=username).values()[0]['passwd']
            #如果用户输入的密码和存储的密码相等
            if passwd==db_passwd:
                #页面跳转重定到百度
                return redirect("https://www.baidu.com")
            else:
                #如果密码验证失败,在页面底部显示错误提示
                return render(request,'login.html',{'error_info': '密码错误'})
                
        #如果没有找到这个用户,就在页面上提示没有这个用户
        else:
            #这个return的返回值会直接返回ajax可以的success:function()
            return HttpResponse('触发ajax')
    return render(request,'login.html')


第二步,我们在templates目录下创建一个login.html

/templates/login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.5-dist/css/bootstrap.min.css">
</head>
<body>
    <div class="container">
        <form action="login.html" method="post">
            <div class="form-group">
                <label class="sr-only">username</label>
{#                用户名输入框#}
                <input type="text" class="form-control" name="username" id="username"  placeholder="用户名"/>
            </div>
            <div class="form-group">
                <label class="sr-only">Password</label>
{#                密码输入框#}
                <input type="password" class="form-control" name="passwd" placeholder="密码"/>
            </div>
            <div class="form-group">
{#                登录按钮#}
                <input class="btn btn-primary" type="submit" value="登录">
            </div>
{#            通过模版语言的变量显示错误提示信息#}
            {{ error_info }}
        </form>
</div>
<script type="application/javascript" src="/static/js/jquery-2.2.1.min.js"></script>
<script type="application/javascript" src="/static/plugins/bootstrap-3.3.5-dist/js/bootstrap.min.js"></script>
<script>
{#    根据<input>的id获取设定输入框焦点离开时的操作#}
    $('#username').blur(function(){
{#       获取用户输入的用户名 #}
       var input_name=$(this).val();
{#       调用ajax提交数据 #}
       $.ajax({
{#                指定提交的url#}
                url:"/login/",
{#                指定将获取的用户名提交给login()函数里的username变量用于验证#}
                data:{username:input_name},
{#                指定提交的数据的格式#}
                type:'POST',
{#                success用来接收login()函数执行之后的return HttpResponse返回值#}
                success:function(arg){
{#                    用arg接收到返回值后通过alert将返回的内容输出到页面上#}
                    alert(arg)
                }
            });
    });
</script>
</body>
</html>


第三步,mydjango子目录下urls.py文件里设置页面与函数的绑定

/mydjango/urls.py

#!/usr/bin/env python
# coding:utf-8
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
]


第四步、在app01应用下的model.py创建数据库表

/app01/model.py

# !/usr/local/env python
# coding:utf-8
from __future__ import unicode_literals
# 首先要导入models方法
from django.db import models
# Create your models here.
"""
编写一个类,类里的参数必须是(models.Model)
类的名字就是要在数据库创建的表名字
"""
class userinfo(models.Model):
    """
    这里的user和passwd就是表中要创建的字段名
    models.CharField表示要创建的字段类型是字符串类型的
    如果创建字符窜类型那么括号里必须指定字符串长度
    """
    user = models.CharField(max_length=30)
    passwd = models.CharField(max_length=30)


第五步、在数据库先创建好测试用的账号alex/12345

wKioL1bnvZfBSr_aAAAbr5cUBJI836.png



最后登录页面开始测试

wKioL1bnvqTyDEqIAABSE6k7Hac066.png

输入了错误的用户名之后,鼠标焦点一离开用户名输入框就马上弹出了alert警告框。说明ajax的异步提交验证已经成功了。输入正确的用户名和错误的密码测试


wKiom1bnvqDCfolDAAAHHANhgwY917.png

这次因为用户名正确所以没有弹出警告框,输入密码之后就能正常的显示处错误信息了。最后的如果用户名和密码都正确也跳转到百度。这个就不贴图了,没什么意义。



ajax发送复杂的数据类型(数组,字典等)


    上面的例子只是将输入用户名拿到后台去进行验证。如果我们要一次提交很多组的数据就需要进行用到字典和数组这种数据类型来处理了。

    为了测试多组数据的提交,我们需要修改一下上面的例子

1、在login页面前面多添加两个输入框,ajax在提交时候一并读附加的输入框内容
2、用户名输入错误的时候会弹出alert框,在alert框体里打印新添加输入框的内容
3、因为要一次提交多条数据,所以新建了一个checkuser()函数处理ajax请求。原来的login()函数用来处理点击按钮时候的验证。


首先、我们修改login.html文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.5-dist/css/bootstrap.min.css">
</head>
<body>
    <div class="container">
        <form action="login.html" method="post">
            <div class="form-group">
                <label class="sr-only">username</label>
{#                性别输入框#}
                <input type="text" class="form-control" name="username" id="sex"  placeholder="性别"/>
            </div>
            <div class="form-group">
                <label class="sr-only">username</label>
{#                爱好输入框#}
                <input type="text" class="form-control" name="username" id="interests"  placeholder="爱好"/>
            </div>
            <div class="form-group">
                <label class="sr-only">username</label>
{#                用户名输入框#}
                <input type="text" class="form-control" name="username" id="username"  placeholder="用户名"/>
            </div>
            <div class="form-group">
                <label class="sr-only">Password</label>
{#                密码输入框#}
                <input type="password" class="form-control" name="passwd" placeholder="密码"/>
            </div>
            <div class="form-group">
{#                登录按钮#}
                <input class="btn btn-primary" type="submit" value="登录">
            </div>
{#            通过模版语言的变量显示错误提示信息#}
            {{ error_info }}
        </form>
</div>
<script type="application/javascript" src="/static/js/jquery-2.2.1.min.js"></script>
<script type="application/javascript" src="/static/plugins/bootstrap-3.3.5-dist/js/bootstrap.min.js"></script>
<script>
{#    根据<input>的id获取设定输入框焦点离开时的操作#}
    $('#username').blur(function(){
{#       获取用户输入的用户名 #}
        var input_sex=$('#sex').val();
        var input_interests=$('#interests').val();
        var input_name=$(this).val();
{#        创建一个数组将要提交的数据都放在数组里#}
        var submit_data=[
            {sex:input_sex},
            {interests:input_interests},
            {username:input_name}
        ];
{#       调用ajax提交数据 #}
        $.ajax({
{#                指定提交的url#}
                url:"/checkuser/",
{#                这里提交的方式还是字典方式,不过key就是data本身 value的值就是上面定义的数组#}
                data:{data:submit_data},
{#                指定提交的数据的格式#}
                type:'POST',
{#                success用来接收login()函数执行之后的return HttpResponse返回值#}
                success:function(arg){
{#                    用arg接收到返回值后通过alert将返回的内容输出到页面上#}
                    alert(arg)
                }
            });
    });
</script>
</body>
</html>

修改完了之后我们登录后台进行提交测试,在后台观察能不能成功获取提交的数组里的数据

wKiom1bn1B2SQkTjAAAepP_f1mw869.png

从结果来可以看出来虽然后台可能够看到获取的内容,但是结构是混乱的我们根本提取不出来。其实这因为我们在配置ajax提交的时候少了一些配置。ajax代码代码应该如下:

$.ajax({
                url:"/login/",
{#                启用原生模式传输#}
                tradition:true,
{#              通过JSON.stringify()方法将数组以json格式转换成字符串#}
                data:{data:JSON.stringify(submit_data)},
                
                type:'POST',
                success:function(arg){
                    alert(arg)
                }
            });

修改之后,我们在来后台观察提交的数据

wKioL1bn12zwG5RpAAAPYjcaM7E844.png现在就已经变成了我们提交时候的格式了。所以我们的最终的login.html代码如下

/templates/login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>login</title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.5-dist/css/bootstrap.min.css">
</head>
<body>
    <div class="container">
        <form action="/login/" method="post">
            <div class="form-group">
                <label class="sr-only">sex</label>
{#                性别输入框#}
                <input type="text" class="form-control" name="sex" id="sex"  placeholder="性别"/>
            </div>
            <div class="form-group">
                <label class="sr-only">sex</label>
{#                爱好输入框#}
                <input type="text" class="form-control" name="interests" id="interests"  placeholder="爱好"/>
            </div>
            <div class="form-group">
                <label class="sr-only">username</label>
{#                用户名输入框#}
                <input type="text" class="form-control" name="username" id="username"  placeholder="用户名"/>
            </div>
            <div class="form-group">
                <label class="sr-only">Password</label>
{#                密码输入框#}
                <input type="password" class="form-control" name="passwd" placeholder="密码"/>
            </div>
            <div class="form-group">
{#                登录按钮#}
                <input class="btn btn-primary" type="submit" value="登录">
            </div>
{#            通过模版语言的变量显示错误提示信息#}
            {{ error_info }}
        </form>
</div>
<script type="application/javascript" src="/static/js/jquery-2.2.1.min.js"></script>
<script type="application/javascript" src="/static/plugins/bootstrap-3.3.5-dist/js/bootstrap.min.js"></script>
<script>
{#    根据<input>的id获取设定输入框焦点离开时的操作#}
    $('#username').blur(function(){
{#       获取用户输入的用户名 #}
        var input_sex=$('#sex').val();
        var input_interests=$('#interests').val();
        var input_name=$(this).val();
{#        创建一个数组将要提交的数据都放在数组里#}
        var submit_data=[
            {sex:input_sex},
            {interests:input_interests},
            {username:input_name}
        ];
{#       调用ajax提交数据 #}
        $.ajax({
{#                因为格式复杂所以单独创建了一个函数处理多条数据#}
                url:"/checkuser/",
{#                启用原生模式传输#}
                tradition:true,
{#              通过JSON.stringify()方法将数组以json格式转换成字符串#}
                data:{data:JSON.stringify(submit_data)},
{#                指定提交的数据的格式#}
                type:'POST',
{#                success用来接收login()函数执行之后的return HttpResponse返回值#}
                success:function(arg){
{#                    因为接收到的是json格式,所以需要调用$.parseJSON方法反序列化#}
                    var callbac_dic= $.parseJSON(arg);
{#                    取出字典里的value值#}
                    alert_str=callbac_dic.alert_info;
                    alert(alert_str)
                }
            });
    });
</script>
</body>
</html>



修改app01应用下的views.py里面的login()函数和新创建一个处理ajax请求的checkuser()函数

/app01/views.py

# /usr/bin/env python
# coding:utf-8
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse
from app01 import models
import json

def login(request):
    # 首先判断页面的请求方式
    #如果是POST就表明有表单内容要提交
    if request.method=='POST':
        # 获取通过提交按钮发来的请求内容
        username=request.POST['username'].strip()
        passwd=request.POST['passwd'].strip()
        #如果用户名能在数据库里找到
        if models.userinfo.objects.filter(user=username):
            #有用户再验证密码
            print request.POST
            print passwd
            db_passwd=models.userinfo.objects.filter(user=username).values()[0]['passwd']
            #如果用户输入的密码和存储的密码相等
            if passwd==db_passwd:
                #导入跳转重定向模块
                return redirect("https://www.baidu.com")
            else:
                return render(request,'login.html',{'error_info': '密码错误'})
        # 如果没有找到这个用户,就在页面上提示没有这个用户
    return render(request,'login.html')
    
    
def checkuser(request):
    #通过ajax提交过来的请求内容
    if request.method=='POST':
        # 因为传过来的是json格式的字典数据,所以需要解开格式
        json_data = request.POST['data']
        # 获得的列表格式为[{"sex":"male"},{"interests":"python"},{"username":"abc"}]
        content=json.loads(json_data)
        #输入的获取用户名
        username=content[2]['username']
        #获取性别
        sex=content[0]['sex']
        #获取爱好
        interests=content[1]['interests']
        #如果数据库中不存在用户名
        if not models.userinfo.objects.filter(user=username):
            # 拼接成新字符串,因为从json反序列化出来的内容都是Unicode的直接给其他变量赋值可能有问题
            #在拼接字符串的时候也把字符串设置成了Unicode格式,避免出现字符集问题
            alert_str=u'sex:%s  interests:%s name:%s'%(sex,interests,username)
            #为了测试把特殊数据格式传回前段,我们把str封装进字典里
            alert_dic={'alert_info':alert_str}
            #因为HttpResponse只能传输字符串,所以我们在用json把字典序列化成字符串
            return HttpResponse(json.dumps(alert_dic))



最后设置mydjango子目录下urls.py文件里的url与函数的绑定关系

#!/usr/bin/env python
# coding:utf-8
from django.conf.urls import url,include
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login),
    url(r'^checkuser/', views.checkuser),
]


最后我们来打开浏览器测试一下修改的内容

wKioL1boMbaAC6RrAAAjF9xys_o042.png


从测试结果来看,我们成功的把多条数据以json格式传入了后端,在后端进行字符串拼接之后又以json格式成功的输出到了前端,达到了我们的目标。