day 74ajax
ajax定义:
AJAX(Asynchronous Javascript And XML)
翻译成中文就是'异步JavaScript和XML',也就是使用JavaScript语言与服务器进行异步交互,传输的数据为XML(不仅仅局限于XML)
day74
整理:
url: /index/ 没有请求数据
url("/index/",index) index(request)
render() 响应一个数据页面
{"user":"yuan","pwd":"123"}
user-yuan,pwd-123
contentType:application/x-www-form-urlencoded
请求web网站的方式:
1、地址栏 url get请求
2、超链接标签 get请求
3、form表单 get请求 post请求
4、Ajax请求 get请求 post请求
Ajax
关于json:
在python中 基于json.dumps() json.loads()
在js中 基于
form组件
我们的ajax是基于我们的js语言来实现的功能.
在了解ajax之前我们需要回顾一下json,
json的定义:
json(JavaScript object notation,js对象标记)是一种轻量级的数据交换格式,它基于ecmascript(w3c指定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据.
简介和清晰的层次结构使得json成为理想的数据交换语言,易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率
我们的json就是序列化用的,基于我们的网络传输的数据都是字符串,我们需要把所有的数据类型转换成字符串才可以进行传输,那么我们的json就是这样一个功能,它负责把所有的数据类型转换成字符串,然后进行传输,一边把数据打包成字符串传过去,对方接受之后把这些字符串再通过解包还原成他们原来的样子,
我们的json打包后的字符串是有固定格式的,如果我们的字符串满足这个格式的话,就不需要再打包了,直接使用我们的json解包即可得到该数据原本的样子.
那么我们的json字符串的固定格式是什么样子的呢?
["one","name","age"]
{"one":1,"name":"alex","age":12}
{"name":["黎明","周雨"]}
[{"name":"李思"},{"name":}]
总结起来就是我们的各种括号里面的元素需要加上"双引号",
不合格的json对象:
{name:"张三",'age':32} //属性名必须使用双引号
[12,22,13,432,OxFF] //不能使用十六进制值
{"name":"李玉","age":undefined} //不能使用undefined
{"name":"张杨","birthday":new Date('Fri,12 Aug 2009 2:39:20 GMT'),
"getName":function() {return this.name;}
} //不能使用函数和日期对象
stringify与parse方法
我们的web请求,分为以下三种:
地址栏 url 直接输入地址即可得到相应的页面 get请求
超链接标签 get请求
form表单 get/post请求
ajax get/post请求
在我们的HTML前端页面上的标签里面有一个属性是enctype,它的属性值有两个,其中一个是我们在浏览器上面上传文件时用的'multipart/form-data'. 还有另外一个就是'application/x-www-form-urlencoded' 这里面的urlencoded它是url的数据编码格式
局部刷新,{我们举例来理解这的概念,在我们的其他的网站的登录注册页面里面,我们的用户名,密码,邮箱等信息不能为空的,但是我们如果为空,然后点击注册按钮的时候,input框周边会弹出提示信息,提示我们的输入不能为空,这个时候我们的点击事件并没有刷新我们的页面,但是我们确实真的刷新了,因为弹出的提示信息我们的输入的用户名已经存在,这很显然是我们的数据已经去到数据库里面过了一遍,这就是刷新的证据}我们在很多的朋友圈或者是微博里面或者是博客里面的时候,有点赞功能,我们的页面不会整个全局刷新,我们点击一下那个点赞的按钮之后看到有数据提交返回给浏览器,但是页面没有刷新都是因为我们的ajax在中间起到的作用
异步请求
客户端发出一个请求后,无需等待服务器响应结束就可以发出第二个请求操作.
我们也举例理解一下这个异步请求的概念
我们在注册页面的时候里面有很多的input框,我们在输入的时候一个框输入完之后就紧接着输入第二个框,在这个过程中one by one,页面都不会刷新,
如图:
这里的图片就是局部刷新的效果.
优点:
ajax使用javasctipt技术向服务器发送异步请求
ajax无须刷新整个页面
因为服务器相应内容不再是整个页面,而是页面中的局部,所以ajax性能高
jQuery实现的ajax代码示例如下图:
ajax其他参数补充:
1 {% load staticfiles %} 2 3 <!DOCTYPE html> 4 5 <html lang="en"> 6 <head> 7 <meta charset="UTF-8"> 8 <title>Title</title> 9 <script src="{% static 'JS/jquery-3.1.1.js' %}"></script> 10 </head> 11 <body> 12 13 <button class="send_Ajax">send_Ajax</button> 14 15 <script> 16 //$.ajax的两种使用方式: 17 18 //$.ajax(settings); 19 //$.ajax(url,[settings]); 20 21 22 $(".send_Ajax").click(function(){ 23 24 $.ajax({ 25 url:"/handle_Ajax/", 26 type:"POST", 27 data:{username:"Yuan",password:123}, 28 29 success:function(data){ 30 alert(data) 31 }, 32 33 //=================== error============ 34 35 error: function (jqXHR, textStatus, err) { 36 37 // jqXHR: jQuery增强的xhr 38 // textStatus: 请求完成状态 39 // err: 底层通过throw抛出的异常对象,值与错误类型有关 40 console.log(arguments); 41 }, 42 43 //=================== complete============ 44 45 complete: function (jqXHR, textStatus) { 46 // jqXHR: jQuery增强的xhr 47 // textStatus: 请求完成状态 success | error 48 console.log('statusCode: %d, statusText: %s', jqXHR.status, jqXHR.statusText); 49 console.log('textStatus: %s', textStatus); 50 }, 51 52 //=================== statusCode============ 53 statusCode: { 54 '403': function (jqXHR, textStatus, err) { 55 console.log(arguments); //注意:后端模拟errror方式:HttpResponse.status_code=500 56 }, 57 58 '400': function () { 59 } 60 } 61 62 }) 63 64 }) 65 66 </script> 67 </body> 68 </html>
ajax参数:
请求参数
1 data:当前ajax请求要求携带的数据,是一个json的objects对象,ajax方法就会默认把它编码成某种格式 2 (urlencoded:?a=1&b=2)发送给服务端,此外,ajax默认以get方式发送请求. 3 function testData(){ 4 5 $.ajax()"/test".{ 6 7 // 此时的data是一个json形式的对象 8 9 data:{ 10 11 a:1, 12 13 b:2 14 15 } 16 17 } 18 19 }; //?a=1&b=2 20 21 22 23 ###########---------------processData-----------------############################## 24 25 processData: 声明当前的data数据是否进行转码或预处理,默认为true,即预处理;if为false,那么对于data:{a:1,b:2}会调用json对象的toString()方法,即{a:1,b:2}.toString(),最后得到一个[object,Object]形式的结果. 26 27 28 29 ####################---------------contentType--------------------###################### 30 31 contentType:默认值:'application/x-www-form-urlencoded'.发送信息至服务器时内容编码类型.用来指明当前请求的数据编码格式;urlencoded:?a=1&b=2;如果想以其他方式提交数据,比如contentType:"application/json",即向服务器发送一个json字符串: 32 33 $.ajax("/ajax_get",{ 34 35 data:JSON.stringify({ 36 37 a:22, 38 39 b:33 40 41 }), 42 43 contentType:"application/JSON", 44 45 type:"POST", 46 47 }); //{a:22,b:33} 48 49 注意:contentType:"application/json"一旦设定,data必须是json字符串,不能是json对象 50 51 views.py:json.loads(request.body.decode("utf8")) 52 53 54 55 ####################----------------traditional-------------############# 56 57 traditional:一般是我们的data数据有数组时会用到:data:{a:22,b:33,c:['x','y']},traditional为false会对数据进行深层次迭代; 58 59
响应参数:
dataType:预期服务器返回的数据类型,服务器端返回的数据会根据这个值解析后,传递给回调函数,
默认不需要显性指定这个属性,ajax会根据服务器返回的content Type来进行转换;比如我们的服务器
相应的content Type为json格式,这时ajax方法就会对相应的内容进行一个json格式的转换,if转换成功,
我们在success的回调函数里就会得到一个json格式的对象;转换失败就会触发error这个回调函数.
如果我们明确地指定目标类型,
就可以使用data Type.dataType的可用值:html|xml|json|text|script
关于ajax的参数的示例:
HTML模板:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <meta name="viewport" content="width=device-width, initial-scale=1"> 7 <title>Title</title> 8 </head> 9 <body> 10 11 <button class="json">hello</button> 12 {% csrf_token %} 13 <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script> 14 <script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script> 15 <script> 16 17 $(".json").click(function(){ 18 19 20 {# $.ajax({#} 21 {# url:"/ajax/",#} 22 {# data:JSON.stringify({"k1":"v1"}),#} 23 {# type:"post",#} 24 {# headers:{"X-CSRFToken":$()},#} 25 {# contentType:"application/json",#} 26 //contentType:默认值:"application/x-www-form-urlencoded"发送信息至服务器时内容编码类型用来指明当前请求的数据编码格式, 27 // urlencoded:?a=1&b=2;如果想以其他方式提交数据,比如contentType:"application/json",即向服务器发送一个json字符串, 28 //注意:contentType:"application/json"一旦设定data必须要就送字符串,不能是json对象 29 //在views视图函数里面,写上json.loads(request.body.decode('utf-8')) 30 //dataType:预期服务器返回的数据类型,服务器返回的数据会根据这个值解析后,传递给回调函数,默认不需要显性指定这个属性, 31 // ajax会根据服务器返回的content Type来进行转换;比如我们的服务器相应的content Type为json格式,这时的ajax方法 32 // 就会对相应的内容进行一个json格式的转换,if转换成功,我们在success的回调函数里就会得到一个json格式的对象,转换失败就会触发 33 // error这个回调函数,如果我们明确地指定目标类型,就可以使用data Type. 34 // data Type的可用值:html|xml|json|text|script 如下就是data Type示例 35 {# success:function(data){#} 36 {# alert(data)#} 37 {# }#} 38 {# });#} 39 40 $.ajax({ 41 url:"/ajax/", 42 dataType:"json", 43 success:function(data){ 44 console.log(data); 45 console.log(typeof(data)); 46 }, 47 error:function(jqXHR, textStatus, 48 err){ 49 //jqXHR:jQuery增强的xhr 50 //textStatus:请求完成状态 51 //err:底层通过throw抛出的异常对象,值与错误类型有关 52 {# console.log(arguments);#} 53 console.log(err); //这里是打印error函数里面的其中一个参数err 54 alert("403 forbidden"); 55 } 56 }); 57 }); 58 </script> 59 </body> 60 </html>
views函数:
1 def ajax(request): 2 """ 3 import json 4 print(request.GET) 5 print(request.POST) 6 print(request.body.decode()) # {"k1":"v1"} 7 print(json.loads(request.body.decode())) # {"k1":"v1"} 8 print(json.loads(request.body.decode()).get("k1") # {"k1":"v1"} 9 :param request: 10 :return: 11 """ 12 # import json 13 # return HttpResponse(json.dumps(["hi"])) 14 # return HttpResponse('{"k1":"v1"}') 15 return HttpResponse("{'k':'v'}") 16 17 18 def home(request): 19 return render(request, 'home.html')
url路由:
url(r^'home/$',views.home), url(r^'ajax/$',views.ajax),
csrf跨站请求伪造
方式1:
$.ajaxSetup({
data:{csrfmiddlewaretoken:'{{csrf_token}}'},
});
方式2
<form>
{% csrf_token %}
</form><br><br><br>$.ajax({<br>....<br>data:{
"csrfmiddlewaretoken":$("[name='csrfmiddlewaretoken']").val();
}<br>})
方式3
<script src="{%static 'js/jquery.cookie.js'%}"></script>
$.ajax({
headers:{"X-CSRFToken":$.cookie('csrftoken')},
})
js实现的ajax
ajax核心(XMLHttpRequest)
其实ajax就是在javascript中添加了一个对象,XMLHttpResponse对象,所有的异步交互都是使用XMLHttpServelet对象完成的,也就是说,我们只需要学习一个javascript的新对象即可.
使用流程:
步骤1:打开与服务器的连接open方法
当得到xmlhttprequest对象后,就可以调用该对象的open方法打开与服务器的连接,open()方法的参数如下:
open(method,url,async):
method:请求方式,通常为get或post;
url:请求的服务器地址,例如:/ajaxdemo,若为get请求,还可以在url后追加参数;
async:这个参数可以不给,默认值为true,表示异步请求;
var xmlhttp=createXMLhttprequest();
xmlHttp.open(
"GET"
,
"/ajax_get/?a=1"
,
true
);
步骤2:发送请求
当使用open打开连接后,就可以调用xmlhttprequest对象的send()方法发送请求了.send()方法的参数为post请求参数,即对应http协议的请求体内容,若是get请求,需要在url后连接参数,
注意:若没有参数需要给出null为参数,若不给出null为参数,可能会导致firefox浏览器不能正常发送请求
xmlhttp.send(null);
步骤3:接收服务器相应
当请求发送出去后,服务器端就开始执行了,但服务器端的响应还没有接收到,接下来我们来接收服务器端的响应
xmlhttprequest对象有一个onreadystatechange事件,他会在xmlhttprequest对象的状态发生变化的时候被调用,下面介绍一下xmlhttprequest对象的5种状态
0:初始化为完成状态,只是创建了xmlhttprequest对象,还未调用open()方法;
1:请求已开始,open()方法已调用,但还没有调用send()方法;
2:请求发送完成状态,send()方法已调用;
3:开始读取服务器相应;
4:读取服务器相应结束.
onreadystatechange事件会在状态为1,2,3,4时引发,
下面代码会被执行4次对应的xmlhttprequest的四种状态!
xmlhttp.onreadystatechange=function(){
alert("hello");
};
但通常我们只关心最后一种状态,即读取服务器响应结束时,客户端才会做出改变。我们可以通过XMLHttpRequest对象的readyState属性来得到XMLHttpRequest对象的状态。
xmlHttp.onreadystatechange = function() { if(xmlHttp.readyState == 4) { alert('hello'); } };
其实我们还要关心服务器相应的状态码是否为200,其服务器相应为404,或500,那么就表示请求失败了,我们可以通过xmlhttprequest对象的status属性得到服务器的状态码.最后,我们还需要获取到服务器相应的内容,可以通过xmlhttprequest对象的responseText得到服务器相应内容.
xmlHttp.onreadystatechange = function() { if(xmlHttp.readyState == 4 && xmlHttp.status == 200) { alert(xmlHttp.responseText); } };
if发送post请求
1,需要设置请求头:xmlhttprequestheader("content-type","application/x-www-form-urlencoded");
注意:form表单会默认这个键值对不设定,web服务器会忽略请求体的内容
2,在发送时可以指定请求体了:xmlhttp.send("username=yuan&password=123")
js实现ajax小结
创建xmlhttprequest对象;
调用open()方法打开与服务器的连接;
调用send()方法发送请求;
为xmlhttprequest对象指定onreadystatechange事件函数,这个函数会在xmlhttprequest的1,2,3,4四种状态时被调用;
xmlhttprequest对象的5种状态,通常我们只关心4种状态,
xmlhttprequest对象的status属性表示服务器状态码,它只有在readystate为4才能获取到,
xmlhttprequest对象的responseText属性表示服务器相应内容,它只有在readyState为4才能获取到
示例:
后端页面:
1 from django.shortcuts import render, HttpResponse 2 from django.urls import reverse 3 from . models import* 4 import logging 5 from django.db.models import Q, F 6 from django import forms 7 from django.forms import widgets 8 from django.core.exceptions import NON_FIELD_ERRORS, ValidationError 9 10 # Create your views here. 11 12 13 # 基于ajax的登录页面 14 def home(request): 15 # print('*&' * 120) # 只有print可以得到结果,而我们的logging根本无从得到像print一样的效果 16 # logging.info('here is'*120) 17 if request.method == 'GET': 18 return render(request, 'hm-bootstrap.html') 19 nm = request.POST.get('name') 20 # pd = request.POST.get('pwd') 21 response = {'bool': True} 22 # print('#'*120) # 同上的效果 23 logging.debug("hello=====================") 24 # if Userinfo.objects.filter(name=nm, pwd=pd): 25 if UserInfo.objects.filter(name=nm): 26 # if models.Userinfo.objects.filter(Q(name=nm) & Q(pwd=pd)): 27 pass 28 else: 29 response['bool'] = False 30 # if models.Userinfo.objects.filter(name=nm) and models.Userinfo.objects.filter(pwd=pd): 31 import json 32 33 return HttpResponse(json.dumps(response))
前端模板:
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 6 <meta name="viewport" content="width=device-width, initial-scale=1"> 7 <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7/css/bootstrap.min.css"> 8 <title>bootstrap-hm</title> 9 <link rel="stylesheet" href="/static/css/hm-bootstrap.css"> 10 </head> 11 <body> 12 <div> 13 <h2 class="container col-md-3 col-lg-offset-5">请登录</h2> 14 </div> 15 <div class="row"> 16 <!--这里我们直接在class里面设置我本身就占4列,然互我再让出左边的4列,name就得到了居中的效果--> 17 <div class="container col-md-4 col-lg-offset-4" id="container"> 18 {# <form class="form-horizontal" action="/home/" method="post">#} 19 20 {% csrf_token %} 21 <div class="form-group"> 22 <label for="inputEmail3" class="col-sm-2 control-label">name</label> 23 <div class="col-sm-9"> 24 <input type="text" class="form-control" id="name" placeholder="name"> 25 <span class="error"></span> 26 </div> 27 </div> 28 <div class="form-group"> 29 <label for="inputPassword3" class="col-sm-2 control-label">password</label> 30 <div class="col-sm-9"> 31 <input type="password" class="form-control" id="pwd" placeholder="Password"> 32 <span class="error"></span> 33 </div> 34 </div> 35 <div class="form-group"> 36 <div class="col-sm-offset-2 col-sm-10"> 37 <div class="checkbox"> 38 <label> 39 <input type="checkbox"> 记住我 40 </label> 41 </div> 42 </div> 43 </div> 44 {# <p style="color:red">{{ error }}</p> {# 这里的大括号套两层是包裹的一个变量,我们需要在后期用到这个变量 #} 45 <div class="form-group"> 46 <div class="col-sm-offset-2 col-sm-10"> 47 <button type="button" class="btn btn-primary col-sm-11">登陆</button> 48 </div> 49 </div> 50 {# </form>#} 51 </div> 52 </div> 53 {#<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>#} 54 <script src="/static/js/jquery-3.2.1.min.js"></script> 55 <script> 56 // 我们这里找到要输入的用户信息 57 $(".form-control").blur(function () { 58 $.ajax({ 59 url: "/home_hm/", 60 type: 'post', 61 data: { 62 "name": $("#name").val(), 63 {# "pwd":$("#pwd").val(),#} 64 "csrfmiddlewaretoken": $("[name='csrfmiddlewaretoken']").val() 65 }, 66 success: function (data) { 67 console.log(data); 68 var data = JSON.parse(data); 69 if (data.bool) { 70 $("#name").next().text('该用户已经注册').css('color', 'red'); 71 {# location.href='http://www.sogo.com'#} 72 } 73 } 74 }) 75 }); 76 77 </script> 78 </body> 79 </html>
我们的前端模板整个js代码就是我们的ajax实现的功能,