Python入门自学进阶-Web框架——7、认识Ajax,与Django交互,基于JS

AJAX(Asynchronous Javascript And XML),即“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。

 

实际上Ajax属于前端技术,因为涉及与后台服务器的交互,即这里与Django的交互,所以就放在这里了。

前面学过的向后台服务器,即Server端发送数据的方式主要有两种:
一是在URL中加上?再加上键值对,http://www.test.com/?key1=value1&key2=value2,相当于form表单的get方式
二是通过form表单的submit按钮,有get和post两种提交方法

这里Ajax是第三种,前两种是显示的提交,我们能够感受到提交的过程,页面会整个刷新一次。Ajax属于隐式提交,我们直观上感觉不到,整个页面没有刷新,只是局部刷新。这是Ajax的一个特点,Ajax的第二个特点是异步交互,前两个是同步交互。

  • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。

Ajax的优缺点:

优点:

  • AJAX使用Javascript技术向服务器发送异步请求;
  • AJAX无须刷新整个页面;
  • 因为服务器响应内容不再是整个页面,而是页面中的局部,所以AJAX性能高;

缺点:

  • AJAX并不适合所有场景,很多时候还是要使用同步交互;
  • AJAX虽然提高了用户体验,但无形中向服务器发送的请求次数增多了,导致服务器压力增大;
  • 因为AJAX是在浏览器中使用Javascript技术完成的,所以还需要处理浏览器兼容性问题;

使用Ajax的操作过程:共分四步

  • 创建核心对象;
  • 使用核心对象打开与服务器的连接;
  • 发送请求
  • 注册监听,监听服务器响应。

第一步创建核心对象,这个对象就是XMLHTTPRequest。

语法:xmlHttp = new XMLHttpRequest();  这个是IE7及以上版本的语法
           xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");   这是IE6的语法
           xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");  这是IE5.5及更早版本的语法

从上面语法可以看出,因为浏览器的版本不同,需要使用不同的语法,这就是兼容性问题

第二步与服务器的交互

连接,在有了核心对象后,就要通过这个对象与服务器进行连接;发送请求以及注册监听

XMLHttpRequest的相关方法、参数如下:

  • open(请求方式, URL, 是否异步)     ——连接服务器
  • send(请求体)     ——请求体的内容,HTTP协议分为请求头和请求体,如果是GET请求,因为GET没有请求体,这里没有内容,一般写成send(null)
  • onreadystatechange,指定监听函数,它会在xmlHttp对象的状态发生变化时被调用
  • readyState,当前xmlHttp对象的状态,其中4状态表示服务器响应结束
  • status:服务器响应的状态码,只有服务器响应结束时才有这个东东,200表示响应成功;
  • responseText:获取服务器的响应体

基于JS的Ajax的实现
step1:var xmlhttp = new XMLHttpRequest()
step2:xmlhttp.open("")
step3:xmlhttp.send(“name=aaa”)
Step4:注册监听函数,监听xmlhttp对象的状态,后台返回的数据保存在responsetext中

 AJAX状态值是指,运行AJAX所经历过的几种状态,无论访问是否成功都将响应的步骤,可以理解成为AJAX运行步骤。如:正在发送,正在响应等,由AJAX对象与服务器交互时所得;使用“ajax.readyState”获得。(由数字1~4单位数字组成)
AJAX状态码是指,无论AJAX访问是否成功,由HTTP协议根据所提交的信息,服务器所返回的HTTP头信息代码,该信息使用“ajax.status”所获得;(由数字1XX,2XX三位数字组成,

在使用AJAX时采用下面的方式判断所获得的信息是否正确:
if(ajax.readyState == 4 && ajax.status == 200) {  putData(ajax.responseText);}

AJAX运行步骤与状态值说明,就是readyState的值:
  在AJAX实际运行当中,对于访问XMLHttpRequest(XHR)时并不是一次完成的,而是分别经历了多种状态后取得的结果,对于这种状态在AJAX中共有5种,分别是:

0 - (未初始化)还没有调用send()方法
1 - (载入)已调用send()方法,正在发送请求
2 - (载入完成)send()方法执行完成,
3 - (交互)正在解析响应内容
4 - (完成)响应内容解析完成,可以在客户端调用了
对于上面的状态,其中“0”状态是在定义后自动具有的状态值,而对于成功访问的状态(得到信息)我们大多数采用“4”进行判断。

0: (Uninitialized) the send( ) method has not yet been invoked.
1: (Loading) the send( ) method has been invoked, request in progress.
2: (Loaded) the send( ) method has completed, entire response received.
3: (Interactive) the response is being parsed.
4: (Completed) the response has been parsed, is ready for harvesting.

status:服务器响应的状态码,主要是HTTP协议规定的:

主要见到的有:200 成功处理了请求,一般情况下都是返回此状态码;404 服务器找不到请求的网页;500 (服务器内部错误) 服务器遇到错误,无法完成请求。

 

 

 代码测试:GET方法提交

页面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button onclick="func1();">ajax提交</button>
<script>
    {#  createXMLHttpRequest()函数用于创建XMLHttpRequest对象  #}
    function createXMLHttpRequest() {
        var xmlHttp;
        // 适用于大多数浏览器,以及IE7和IE更高版本
        try{
            xmlHttp = new XMLHttpRequest();
        } catch (e) {
            // 适用于IE6
            try {
                xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                // 适用于IE5.5,以及IE更早版本
                try{
                    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e){}
            }
        }
        return xmlHttp;
    }
    function func1() {
        {# step1:创建XMLHttpRequest对象 #}
        var ajaxobj = createXMLHttpRequest();
        {#step2:连接服务器 #}
        ajaxobj.open("GET","/app01/ajax_rec/",true);
        {#step3:发送请求体 #}
        ajaxobj.send(null);
        {# step4:注册监听函数,监听状态变化,在连接到第四步并且HTTP返回码为200,即OK时获取返回数据 #}
        ajaxobj.onreadystatechange = function () {
            {#alert(ajaxobj.readyState)#}
            if(ajaxobj.readyState==4 && ajaxobj.status==200){
                var data = ajaxobj.responseText;
                alert(data);
            }
        }
    }
</script>
</body>
</html>

urls.py中添加路由项(注意是在应用中的urls添加,所以实际路径加上应用名):
path('testajax/',views_app01.testajax),      完整路由项:/app01/testajax/
path('ajax_rec/',views_app01.ajax_rec),     完整路由项:/app01/aja_rec/

视图函数:

def testajax(req):
    return render(req,"testajax.html")

def ajax_rec(req):
    return HttpResponse("hello")

运行:

 点击按钮:

function func1() {
        {# step1:创建XMLHttpRequest对象 #}
        var ajaxobj = createXMLHttpRequest();
        {# 推荐将第四步写在这里 #}
        {# step4:注册监听函数,监听状态变化,在连接到第四步并且HTTP返回码为200,即OK时获取返回数据 #}
        ajaxobj.onreadystatechange = function () {
            {#alert(ajaxobj.readyState)#}
            if(ajaxobj.readyState==4 && ajaxobj.status==200){
                var data = ajaxobj.responseText;
                alert(data);
            }
        }
        {#step2:连接服务器 #}
        ajaxobj.open("GET","/app01/ajax_rec/",true);
        {#step3:发送请求体 #}
        ajaxobj.send(null);
       
    }

推荐将第四步,即注册监听放在创建对象之后。

POST方法提交:

基本使用:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button onclick="func1();">ajax提交</button>
</body>
<script>
    {#  createXMLHttpRequest()函数用于创建XMLHttpRequest对象  #}
    function createXMLHttpRequest() {
        var xmlHttp;
        // 适用于大多数浏览器,以及IE7和IE更高版本
        try{
            xmlHttp = new XMLHttpRequest();
        } catch (e) {
            // 适用于IE6
            try {
                xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                // 适用于IE5.5,以及IE更早版本
                try{
                    xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e){}
            }
        }
        return xmlHttp;
    }
    function func1() {
        {# step1:创建XMLHttpRequest对象 #}
        var ajaxobj = createXMLHttpRequest();
        {# step4:注册监听函数,监听状态变化,在连接到第四步并且HTTP返回码为200,即OK时获取返回数据 #}
        ajaxobj.onreadystatechange = function () {
            {#alert(ajaxobj.readyState)#}
            if(ajaxobj.readyState===4 && ajaxobj.status===200){
                var data = ajaxobj.responseText;
                alert(data);
            }
        }
        {#step2:连接服务器 #}
        {#ajaxobj.open("GET","/app01/ajax_rec/",true);#}
        ajaxobj.open("POST","/app01/ajax_rec/",true);
        {#step3:发送请求体 #}
        {#ajaxobj.send(null);#}
        {# 使用POST提交,必须设置请求头中Content-Type,告诉浏览器请求体中数据的存放格式,即key1=value1&key2=value2.。。   #}
        {# 当没有设置Content-Type为application/x-www-form-urlencoded时,Web容器会忽略请求体的内容,所以在使用ajax发送POST请求时,需要设置这一请求头 #}
        {# 相对于form表单提交,在写form标签时,<form action="" method="post" enctype="x-www-form-urlencoded">,有个默认的enctype,没写就是这个值 #}
        {# 位置放在open之后,send之前,否则出错 #}
        ajaxobj.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
        ajaxobj.send("name1=abcd&name2=1234");
    }
</script>
</html>

此代码将前面的GET提交改为POST提交,除了在open中将GET改为POST,最主要的就是添加:
setRequestHeader("Content-Type","application/x-www-form-urlencoded"),并且对其代码的位置有要求,要在open之后,send之前。

用户注册,在输入完用户名后,使用ajax提交验证是否用户已注册:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>欢迎登陆!!</h1>
<hr>
    <form action="/app01/register/" method="post">
        <P>用户名:<input type="text" name="username"  onblur="func1(this);">
            <span id="err1"></span>
        </P>
        <p>密  码:<input type="text" name="pass"></P>
        <input type="submit" value="submit">
        {% csrf_token %}
    </form>
<script>
    function createXMLHttpRequest(){
        return (new XMLHttpRequest());
    }
    function  func1(self) {
        {#var username = self.getAttribute("value");#}
        {#alert(username);#}
        {# 注意这时username是null,这个跟getAttribute方法有关,使用self.value格式 #}
        var username = self.value;
        var xmlhttpobj = createXMLHttpRequest();
        xmlhttpobj.open("POST","/app01/register/",true);
        xmlhttpobj.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
        xmlhttpobj.send("username="+username);
        xmlhttpobj.onreadystatechange = function () {
            if(xmlhttpobj.readyState ===4 && xmlhttpobj.status === 200){
                var flag_u = xmlhttpobj.responseText;
                if(flag_u == "1"){
                    document.getElementById("err1").innerHTML="用户存在";
                }
            }
        }
    }
</script>
</body>
</html>
def register(req):
    if req.method == "POST":
        username = req.POST.get("username")
        if username == "aaabbb":
            return HttpResponse("1")
        return HttpResponse("0")
    return render(req,"registerpage.html")

运行结果:

这里除了演示ajax的POST使用,测试中还有一个知识点,就是前端input标签的value属性获取方法:
使用getAttribute(“value”)只能获取到input标签中显式定义的value属性的值或使用setAttribute(“value”,“aaabbb”)设置的value属性的值,无法获取输入框中输入的值,获取输入框中的值需要使用点加value的格式,即input.value

<input type="text" name="username" value="pp123">
如上的input标签,这时使用getAttribute(“value”)能取到值为pp123,说明input标签有value属性,如果是:<input type="text" name="username">,getAttribute(“value”)就取不到数据,结果为null,通过后端打印POST值,得出如下结论:
input标签只有显式在标签中写上value="xxx"时,才说明input有value属性,才能使用getAttribute方法获取到value属性的值,或者在没有显式写上value=“xx”,但是在程序中通过setAttribute(“value”,“xxx”)时,也能或取到value属性值。而input输入框中内容是通过input.value保存的,随输入框的内容改变而改变。如果input标签中写了value=“xx”,输入框中的内容初始值是value属性的值xx,输入框内容改变了,只是input.value的值变了,而属性value的值还是原来,属性value的值不会随输入框的内容改变而改变,传递到后台的POST数据内容,是input中的name属性的值为key,输入框的内容为value的键值对,与value属性的值无关,如上的input标签,发到后台的是:username:input.value。

基于jQuery的Ajax的实现:见下一章

=============================================================

1开头的http状态码
表示临时响应并需要请求者继续执行操作的状态代码。
100 (继续) 请求者应当继续提出请求。 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。
101 (切换协议) 请求者已要求服务器切换协议,服务器已确认并准备切换。

2开头的http状态码
表示请求成功
200 成功处理了请求,一般情况下都是返回此状态码;
201 请求成功并且服务器创建了新的资源。
202 接受请求但没创建资源;
203 返回另一资源的请求;
204 服务器成功处理了请求,但没有返回任何内容;
205 服务器成功处理了请求,但没有返回任何内容;重置内容,可能需要请求者重置表单内容
206 处理部分请求;

3xx (重定向)
重定向代码,也是常见的代码
300 (多种选择) 针对请求,服务器可执行多种操作。 服务器可根据请求者 (user agent) 选择一项操作,或提供操作列表供请求者选择。
301 (永久移动) 请求的网页已永久移动到新位置。 服务器返回此响应(对 GET 或 HEAD 请求的响应)时,会自动将请求者转到新位置。
302 (临时移动) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。
303 (查看其他位置) 请求者应当对不同的位置使用单独的 GET 请求来检索响应时,服务器返回此代码。
304 (未修改) 自从上次请求后,请求的网页未修改过。 服务器返回此响应时,不会返回网页内容。
305 (使用代理) 请求者只能使用代理访问请求的网页。 如果服务器返回此响应,还表示请求者应使用代理。
307 (临时重定向) 服务器目前从不同位置的网页响应请求,但请求者应继续使用原有位置来进行以后的请求。

4xx 表示请求出错
400 服务器不理解请求的语法。
401 请求要求身份验证。 对于需要登录的网页,服务器可能返回此响应。ps:该请求表示用户没有认证,无法进行该操作
403 服务器拒绝请求,用户访问被禁止
(401是用户没有提供任何参数,而403是用户提供了参数,但未通过验证)
404 服务器找不到请求的网页。
405 禁用请求中指定的方法。
406 无法使用请求的内容特性响应请求的网页。
407 此状态代码与 401类似,但指定请求者应当授权使用代理。
408 服务器等候请求时发生超时。
409 服务器在完成请求时发生冲突。 服务器必须在响应中包含有关冲突的信息。
410 如果请求的资源已永久删除,服务器就会返回此响应。
411 服务器不接受不含有效内容长度标头字段的请求。
412 服务器未满足请求者在请求中设置的其中一个前提条件。
413 服务器无法处理请求,因为请求实体过大,超出服务器的处理能力。
414 请求的 URI(通常为网址)过长,服务器无法处理。
415 请求的格式不受请求页面的支持。
416 如果页面无法提供请求的范围,则服务器会返回此状态代码。
417 服务器未满足”期望”请求标头字段的要求。

5开头状态码并不常见,但是我们应该知道

500 (服务器内部错误) 服务器遇到错误,无法完成请求。
501 (尚未实施) 服务器不具备完成请求的功能。 例如,服务器无法识别请求方法时可能会返回此代码。
502 (错误网关) 服务器作为网关或代理,从上游服务器收到无效响应。
503 (服务不可用) 服务器目前无法使用(由于超载或停机维护)。 通常,这只是暂时状态。
504 (网关超时) 服务器作为网关或代理,但是没有及时从上游服务器收到请求。
505 (HTTP 版本不受支持) 服务器不支持请求中所用的 HTTP 协议版本。
===========================================================

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值