**一 什么是Ajax **
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。
同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
AJAX除了异步 的特点外,还有一个就是:浏览器页面局部刷新 ;(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
场景:
优点:
AJAX使用Javascript技术向服务器发送异步请求
AJAX无须刷新整个页面
二 基于jquery的Ajax实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 <button class ="send_Ajax" > send_Ajax</button > <script > $(".send_Ajax" ).click (function ( ){ $.ajax ({ url :"/handle_Ajax/" , type :"POST" , data :{username :"Yuan" ,password :123 }, success :function (data ){ console .log (data) }, error : function (jqXHR, textStatus, err ) { console .log (arguments ); }, complete : function (jqXHR, textStatus ) { console .log (textStatus); }, statusCode : { '403' : function (jqXHR, textStatus, err ) { console .log (arguments ); }, '400' : function (jqXHR, textStatus, err ) { console .log (arguments ); } } }) }) </script >
Ajax—->服务器——>Ajax执行流程图
三 案例 一 通过Ajax,实现前端输入两个数字,服务器做加法,返回到前端页面 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 def test_ajax(requests ) : n1=int (requests.POST . get('n1')) n2=int (requests.POST . get('n2')) return HttpResponse(n1 +n2 ) $("#submit" ) .click(function () { $.ajax({ url: '/test_ajax/', type : 'post', data: { n1: $("#num1" ) .val () , n2: $("#num2" ) .val () }, success: function (data) { console.log(data) $("#sum" ) .val (data) }, }) }) <input type ="text" id="num1" >+<input type ="text" id="num2" >=<input type ="text" id="sum" > <button id="submit" >计算</button>
二 基于Ajax进行登录验证 用户在表单输入用户名与密码,通过Ajax提交给服务器,服务器验证后返回响应信息,客户端通过响应信息确定是否登录成功,成功,则跳转到首页,否则,在页面上显示相应的错误信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 def auth(request): back_dic={'user' :None,'message' :None} name=request.POST.get ('user' ) password=request.POST.get ('password' ) print(name) print(password) user=models.user.objects.filter(name=name,password=password).first() print(user) # print(user.query) if user: back_dic['user' ]=user.name back_dic['message' ]='成功' else : back_dic['message' ]='用户名或密码错误' import json return HttpResponse(json.dumps(back_dic)) $("#submit3" ).click(function () { $.ajax({ url: '/auth/' , type: 'post' , data : { 'user' : $("#id_name" ).val (), 'password' : $('#id_password' ).val () }, success: function (data ) { {#console.log(data )#} var data =JSON.parse(data ) if (data .user){ location.href='https://www.baidu.com' }else { $(".error" ).html(data .message).css({'color' :'red' ,'margin-left' :'20px' }) } } }) } )
traditional:true—>可以序列化一层列表,多层不行,要转成json格式上传
四 文件上传 请求头ContentType 这应该是最常见的 POST 提交数据的方式了。浏览器的原生
表单,如果不设置 enctype
属性,那么最终就会以 application/x-www-form-urlencoded 方式提交数据。请求类似于下面这样(无关的请求头在本文中都省略掉了):
1 2 3 4 POST http://www.example.com HTTP/1.1 Content-Type : application/x-www-form-urlencoded;charset=utf-8user =lqz&age=22
这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 表单的 enctype
等于 multipart/form-data。直接来看一个请求示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 POST http://www.example.com HTTP/1.1 Content-Type :multipart/form -data ; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA ------WebKitFormBoundaryrGKCBY7qhFd3TrwA Content-Disposition: form -data ; name ="user" yuan ------WebKitFormBoundaryrGKCBY7qhFd3TrwA Content-Disposition: form -data ; name ="file" ; filename="chrome.png" Content-Type : image/png PNG ... content of chrome.png ... ------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
这个例子稍微复杂点。首先生成了一个 boundary 用于分割不同的字段,为了避免与正文内容重复,boundary 很长很复杂。然后 Content-Type 里指明了数据是以 multipart/form-data 来编码,本次请求的 boundary 是什么内容。消息主体里按照字段个数又分为多个结构类似的部分,每部分都是以 --boundary
开始,紧接着是内容描述信息,然后是回车,最后是字段具体内容(文本或二进制)。如果传输的是文件,还要包含文件名和文件类型信息。消息主体最后以 --boundary--
标示结束。关于 multipart/form-data 的详细定义,请前往 rfc1867 查看。
这种方式一般用来上传文件,各大服务端语言对它也有着良好的支持。
上面提到的这两种 POST 数据的方式,都是浏览器原生支持的,而且现阶段标准中原生 表单也只支持这两种方式 (通过 元素的 enctype
属性指定,默认为 application/x-www-form-urlencoded
。其实 enctype
还支持 text/plain
,不过用得非常少)。
随着越来越多的 Web 站点,尤其是 WebApp,全部使用 Ajax 进行数据交互之后,我们完全可以定义新的数据提交方式,给开发带来更多便利。
3 application/json application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。
JSON 格式支持比键值对复杂得多的结构化数据,这一点也很有用。记得我几年前做一个项目时,需要提交的数据层次非常深,我就是把数据 JSON 序列化之后来提交的。不过当时我是把 JSON 字符串作为 val,仍然放在键值对里,以 x-www-form-urlencoded 方式提交。
1 2 3 4 5 <form action= "/file_put/" method= "post" enctype= "multipart/form-data" > 用户名:<input type= "text" name= "name" > 头像:<input type= "file" name= "avatar" id= "avatar1" > <input type= "submit" value= "提交" > </form>
必须指定 enctype=”multipart/form-data”
视图函数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 def file_put(request): if request.method =='GET': return render(request,'file_put.html' ) else : # print (request.POST) # print (request.POST) print (request.body) # 原始的请求体数据 print (request.GET) # GET请求数据 print (request.POST) # POST请求数据 print (request.FILES) # 上传的文件数据 # print (request.body.decode('utf-8' )) print (request.body.decode('utf-8' )) print (request.FILES) file_obj =request.FILES.get('avatar') print (type(file_obj)) with open(file_obj.name,'wb' ) as f: for line in file_obj: f.write(line) return HttpResponse('ok' )
基于Ajax上传文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 $("#ajax_button" ).click(function ( ) { var formdata=new FormData() formdata.append('name' ,$("#id_name2" ).val()) formdata.append('avatar' ,$("#avatar2" )[0 ].files[0 ]) $.ajax({ url :'' , type :'post' , processData :false , contentType:false , data:formdata, success :function (data ) { console .log (data) } }) })
浏览器请求头为:
Content-Type:
multipart/form-data; boundary=—-WebKitFormBoundaryA5O53SvUXJaF11O2
五 Ajax提交json格式数据 1 2 3 4 5 6 7 8 9 10 11 12 13 14 $("#ajax_test" ).click(function ( ) { var dic={'name' :'lqz' ,'age' :18 } $.ajax({ url :'' , type :'post' , contentType :'application/json' , data:JSON.stringify(dic), success:function (data ) { console .log (data) } }) })
提交到服务器的数据都在 request.body 里,取出来自行处理
六 Django内置的serializers(把对象序列化成json字符串) 1 2 3 4 5 6 from django.core import serializersfrom django.core import serializersdef test (request ): book_list = Book.objects.all () ret = serializers.serialize("json" , book_list) return HttpResponse(ret)