python Django之Ajax
AJAX,Asynchronous JavaScript and XML (異步的JavaScript和XML),一種創建交互式網頁應用的網頁開發技術方案。
- 異步的JavaScript:
使用 【JavaScript語言】 以及 相關【瀏覽器提供類庫】 的功能向服務端發送請求,當服務端處理完請求之后,【自動執行某個JavaScript的回調函數】。
PS:以上請求和響應的整個過程是【偷偷】進行的,頁面上無任何感知。 - XML
XML是一種標記語言,是Ajax在和后台交互時傳輸數據的格式之一
一、原生AJAX
Ajax主要就是使用 【XmlHttpRequest】對象來完成請求的操作,該對象在主流瀏覽器中均存在(除早起的IE),Ajax首次出現IE5.5中存在(ActiveX控件)。
1、XmlHttpRequest對象介紹
我們一般使用都是通過jquery來引用Ajax(jquery本身沒有Ajax功能,它只是Ajax的搬運工)
原生Ajax使用案例如下:

1 from django.conf.urls import url 2 from django.contrib import admin 3 from app01 import views 4 urlpatterns = [ 5 url(r'^admin/', admin.site.urls), 6 url(r'^add1/', views.add1), 7 url(r'^add2/', views.add2), 8 url(r'^fake_ajax/', views.fake_ajax), 9 ]

1 from django.shortcuts import render,redirect,HttpResponse 2 3 # Create your views here. 4 5 def add1(request): 6 a1= int(request.POST.get('i1')) 7 a2= int(request.POST.get('i2')) 8 return HttpResponse(a1+a2) 9 10 11 def add2(request): 12 if request.method=='GET': 13 i1=request.GET.get('i1') 14 i2=request.GET.get('i2') 15 print('add2.....') 16 return HttpResponse(i1+i2)

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <input type="text" name="i1"> 9 + 10 <input type="text" name="i2"> 11 = 12 <input type="text" name="i3"> 13 <input type="button" id="btn1" value="jQuery Ajax" onclick="add1()"> 14 {#綁定一個點擊事件#} 15 <input type="button" id="btn2" value="原生 Ajax" onclick="add2()"> 16 {#綁定一個點擊事件#} 17 <script src="/static/jquery-3.2.1.js"></script> 18 <script> 19 {#=============================================常用方式========================================#} 20 function add1() { 21 $.ajax({ 22 url:'/add1/', 23 type:'POST', 24 data:{'i1':$('#i1').val(),'i2':$('#i2').val()}, 25 {#通過jquery獲取標簽的值#} 26 success:function (arg) { 27 {#回調函數,把arg參數傳進去#} 28 $('#i3').val(arg); 29 {#通過jquery設置i3標簽的值為arg變量的內容#} 30 } 31 }) 32 } 33 34 35 function add2() { 36 {# ==========================================原生Ajax GET方式======================================#} 37 var xhr =new XMLHttpRequest(); 38 {#使用原生的Ajax 創建一個對象#} 39 xhr.onreadystatechange=function () { 40 {#為對象設置回調函數#} 41 if(xhr.readyState==4){ 42 {#如果對象執行時的數值等於4就執行下邊的#} 43 alert(xhr.responseText); 44 {#彈出提示框,框內的內容是對象返回的文本信息#} 45 } 46 47 }; 48 xhr.open('GET','/add2/?i1=12&i2=19'); 49 {#通過對象創建一個連接 參數(GET傳輸方式,/add2/傳輸的地址url ?i1=12&i2=19這是放在url上的數據) 通過get方式傳輸,把傳輸的內容放在請求頭中,傳輸到/add2/url#} 50 xhr.send(); 51 {#對象調用進行發送#} 52 53 54 {# ==========================================POST方式======================================#} 55 var xhr =new XMLHttpRequest() 56 xhr.onreadystatechange = function () { 57 if (xhr.readyState == 4){ 58 alert(xhr.responseText); 59 } 60 61 } 62 }; 63 xhr.open('POST','/add2/'); 64 {#通過對象創建一個連接 參數(post傳輸方式,/add2/傳輸的地址url ) 通過get方式傳輸,把傳輸的內容放在請求體中,傳輸到/add2/url#} 65 xhr.setRequestHeader('Content-Type','application/x-www-from-urlencoded'); 66 {#設置請求體,因為后端需要進行請求體的校驗#} 67 xhr.send('i1=12&i2=19'); 68 {#設置要發送的數據#} 69 </script> 70 </body> 71 </html>
XmlHttpRequest對象的主要方法:
a. void open(String method,String url,Boolen async) 用於創建請求 參數: method: 請求方式(字符串類型),如:POST、GET、DELETE... url: 要請求的地址(字符串類型) async: 是否異步(布爾類型) b. void send(String body) 用於發送請求 參數: body: 要發送的數據(字符串類型) c. void setRequestHeader(String header,String value) 用於設置請求頭 參數: header: 請求頭的key(字符串類型) vlaue: 請求頭的value(字符串類型) d. String getAllResponseHeaders() 獲取所有響應頭 返回值: 響應頭數據(字符串類型) e. String getResponseHeader(String header) 獲取響應頭中指定header的值 參數: header: 響應頭的key(字符串類型) 返回值: 響應頭中指定的header對應的值 f. void abort() 終止請求
XmlHttpRequest對象的主要屬性:
a. Number readyState 狀態值(整數) 詳細: 0-未初始化,尚未調用open()方法; 1-啟動,調用了open()方法,未調用send()方法; 2-發送,已經調用了send()方法,未接收到響應; 3-接收,已經接收到部分響應數據; 4-完成,已經接收到全部響應數據; b. Function onreadystatechange 當readyState的值改變時自動觸發執行其對應的函數(回調函數) c. String responseText 服務器返回的數據(字符串類型) d. XmlDocument responseXML 服務器返回的數據(Xml對象) e. Number states 狀態碼(整數),如:200、404... f. String statesText 狀態文本(字符串),如:OK、NotFound...
jQuery Ajax
jQuery其實就是一個JavaScript的類庫,其將復雜的功能做了上層封裝,使得開發者可以在其基礎上寫更少的代碼實現更多的功能。
- jQuery 不是生產者,而是大自然搬運工。
- jQuery Ajax本質 XMLHttpRequest 或 ActiveXObject

1 jQuery.get(...) 2 所有參數: 3 url: 待載入頁面的URL地址 4 data: 待發送 Key/value 參數。 5 success: 載入成功時回調函數。 6 dataType: 返回內容格式,xml, json, script, text, html 7 8 9 jQuery.post(...) 10 所有參數: 11 url: 待載入頁面的URL地址 12 data: 待發送 Key/value 參數 13 success: 載入成功時回調函數 14 dataType: 返回內容格式,xml, json, script, text, html 15 16 17 jQuery.getJSON(...) 18 所有參數: 19 url: 待載入頁面的URL地址 20 data: 待發送 Key/value 參數。 21 success: 載入成功時回調函數。 22 23 24 jQuery.getScript(...) 25 所有參數: 26 url: 待載入頁面的URL地址 27 data: 待發送 Key/value 參數。 28 success: 載入成功時回調函數。 29 30 31 jQuery.ajax(...) 32 33 部分參數: 34 35 url:請求地址 36 type:請求方式,GET、POST(1.9.0之后用method) 37 headers:請求頭 38 data:要發送的數據 39 contentType:即將發送信息至服務器的內容編碼類型(默認: "application/x-www-form-urlencoded; charset=UTF-8") 40 async:是否異步 41 timeout:設置請求超時時間(毫秒) 42 43 beforeSend:發送請求前執行的函數(全局) 44 complete:完成之后執行的回調函數(全局) 45 success:成功之后執行的回調函數(全局) 46 error:失敗之后執行的回調函數(全局) 47 48 49 accepts:通過請求頭發送給服務器,告訴服務器當前客戶端課接受的數據類型 50 dataType:將服務器端返回的數據轉換成指定類型 51 "xml": 將服務器端返回的內容轉換成xml格式 52 "text": 將服務器端返回的內容轉換成普通文本格式 53 "html": 將服務器端返回的內容轉換成普通文本格式,在插入DOM中時,如果包含JavaScript標簽,則會嘗試去執行。 54 "script": 嘗試將返回值當作JavaScript去執行,然后再將服務器端返回的內容轉換成普通文本格式 55 "json": 將服務器端返回的內容轉換成相應的JavaScript對象 56 "jsonp": JSONP 格式 57 使用 JSONP 形式調用函數時,如 "myurl?callback=?" jQuery 將自動替換 ? 為正確的函數名,以執行回調函數 58 59 如果不指定,jQuery 將自動根據HTTP包MIME信息返回相應類型(an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string 60 61 converters: 轉換器,將服務器端的內容根據指定的dataType轉換類型,並傳值給success回調函數 62 $.ajax({ 63 accepts: { 64 mycustomtype: 'application/x-some-custom-type' 65 }, 66 67 // Expect a `mycustomtype` back from server 68 dataType: 'mycustomtype' 69 70 // Instructions for how to deserialize a `mycustomtype` 71 converters: { 72 'text mycustomtype': function(result) { 73 // Do Stuff 74 return newresult; 75 } 76 }, 77 });

1 <!DOCTYPE html> 2 <html> 3 <head lang="en"> 4 <meta charset="UTF-8"> 5 <title></title> 6 </head> 7 <body> 8 9 <p> 10 <input type="button" onclick="XmlSendRequest();" value='Ajax請求' /> 11 </p> 12 13 14 <script type="text/javascript" src="jquery-1.12.4.js"></script> 15 <script> 16 17 function JqSendRequest(){ 18 $.ajax({ 19 url: "http://c2.com:8000/test/", 20 type: 'GET', 21 dataType: 'text', 22 success: function(data, statusText, xmlHttpRequest){ 23 console.log(data); 24 } 25 }) 26 } 27 28 29 </script> 30 </body> 31 </html>
二、偽Ajax 顧名思義Ajax就是偽造而成的
由於HTML標簽的iframe標簽具有局部加載內容的特性,所以可以使用其來偽造Ajax請求。
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <div> <p>請輸入要加載的地址:<span id="currentTime"></span></p> <p> <input id="url" type="text" /> <input type="button" value="刷新" onclick="LoadPage();"> </p> </div> <div> <h3>加載頁面位置:</h3> <iframe id="iframePosition" style="width: 100%;height: 500px;"></iframe> </div> <script type="text/javascript"> window.onload= function(){ var myDate = new Date(); document.getElementById('currentTime').innerText = myDate.getTime(); }; function LoadPage(){ var targetUrl = document.getElementById('url').value; document.getElementById("iframePosition").src = targetUrl; } </script> </body> </html>

1 def fake_ajax(request): 2 print(request.POST) 3 return render(request,'fake_ajax.html',{'obj':'提交成功'})

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <form id="f1" method="POST" action="fake_ajax" target="ifr"> 9 {#通過form標簽指定以post傳輸 傳輸的url是fake_ajax 提交方式使用form表單里的ifr 這樣就達到不刷新頁面也能把所有信息打包發送#} 10 {% csrf_token %} 11 {#csrf驗證#} 12 <input type="text" name="user"> 13 <a onclick="submitForm();">提交</a> 14 {#綁定點擊事件#} 15 <iframe id="ifr" name="ifr" src="http://www.baidu.com" width="1000px" height="2000px"></iframe> 16 {#使用iframe 標簽 訪問http://www.baidu.com鏈接 這樣就成功的偽造了一個Ajax#} 17 </form> 18 <script> 19 function submitForm() { 20 {#定義函數#} 21 document.getElementById('ifr').onclick=loadIframe; 22 {#查找id是ifr的標簽設置一個點擊事件,相當於綁定一個回調函數#} 23 document.getElementById('f1').submit(); 24 {#找到id是f1的標簽.觸發提交函數#} 25 } 26 27 function loadIframe() { 28 {#定義一個相當於回調函數的函數#} 29 alert(123); 30 } 31 </script> 32 </body> 33 </html>
三、使用原生Ajax做一個文件上傳功能

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 9 <h1>原生Ajax上傳文件</h1> 10 <input type="file" id="i1"> 11 <a onclick="upload1();">上傳</a> 12 <div id="container1"></div> 13 14 15 16 {#======================================================原生Ajax上傳文件======================================#} 17 function upload1() { 18 {#定義一個點擊事件函數#} 19 var formData =new FormData(); 20 {#通過FornData 實例化一個對象,FormData是個特殊的功能,可以傳輸文件和字符串#} 21 formData.append('k1','v1'); 22 {#給對象添加倆個值鍵是k1 值是v1#} 23 formData.append('fafafa',document.getElementById('i1').files[0]); 24 {#給對象添加鍵是fafafa 值是i1標簽的第一個#} 25 var xhr =new XMLHttpRequest(); 26 {#實例化一個對象#} 27 xhr.onreadystatechange =function () { 28 {#給對象設置一個回調函數#} 29 if (xhr.readyState==4){ 30 {#判斷如果xhr對象的執行數字等於4#} 31 var file_path =xhr.responseText; 32 {#獲取對象的文本信息賦值給file_path responseText是返回文本字符串#} 33 var tag = document.createElement('img'); 34 {#創建一個img標簽,標簽名字是tag#} 35 tag.src='/'+file_path; 36 {#通過標簽名創建一個圖片路徑#} 37 document.getElementById('container1').appendChild(tag); 38 {#通過id找到container1標簽 然后再通過標簽的名添加個子標簽#} 39 } 40 } 41 }; 42 xhr.open('POST','/upload/'); 43 {#對象調用open方法創建一個連接,參數post傳輸方式 /upload/傳輸地址url#} 44 xhr.send(formData); 45 {#通過對象發送FormData實例化的對象#} 46 47 48 </script> 49 </body> 50 </html>

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 9 10 <h1>JQuery Ajax上傳文件</h1> 11 <input type="file" id="i2"> 12 <a onclick="upload2();">上傳</a> 13 <div id="container2"></div> 14 15 16 {#======================================================JQuery Ajax上傳文件======================================#} 17 function upload2() { 18 {#定義一個函數#} 19 var formData =new FormData(); 20 {#通過FornData 實例化一個對象,FormData是個特殊的功能,可以傳輸文件和字符串#} 21 formData.append('k1','v1'); 22 {#給對象添加倆個值鍵是k1 值是v1#} 23 formData.append('fafafa',$('#i2')[0].files[0]); 24 {#把fafafa作為鍵 值是id等於i2的標簽轉換成Dom對象的第一個#} 25 $.ajax({ 26 url:'/upload/', 27 type:'POST', 28 data:formData, 29 contentType:false, 30 {#告訴后端不進行請求頭設置#} 31 processData:false, 32 {#告訴后端不進行請求頭設置#} 33 success:function (arg) { 34 {#回調函數#} 35 var tag =document.createElement('img'); 36 {#創建一個img標簽名稱為tag#} 37 tag.src='/'+arg; 38 {#為名字為tag的標簽設置路徑#} 39 $('#container2').append(tag); 40 {#為id是container2標簽的添加名字是tag的標簽為子標簽#} 41 } 42 }) 43 44 } 45 46 47 48 49 </script> 50 </body> 51 </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>原生Ajax上傳文件</h1> <input type="file" id="i1"> <a onclick="upload1();">上傳</a> <div id="container1"></div> <h1>JQuery Ajax上傳文件</h1> <input type="file" id="i2"> <a onclick="upload2();">上傳</a> <div id="container2"></div> <h1>偽 Ajax上傳文件</h1> <form id="f1" method="POST" action="/upload/" target="ifr" enctype="multipart/form-data"> <iframe id="ifr" name="ifr" src="" style="display: none"></iframe> <input type="file" name="fafafa"> <a onclick="upload3();">上傳</a> </form> <div id="container3"></div> <script src="/static/jquery-3.2.1.js"></script> <script> {#======================================================原生Ajax上傳文件======================================#} function upload1() { {#定義一個點擊事件函數#} var formData =new FormData(); {#通過FornData 實例化一個對象,FormData是個特殊的功能,可以傳輸文件和字符串#} formData.append('k1','v1'); {#給對象添加倆個值鍵是k1 值是v1#} formData.append('fafafa',document.getElementById('i1').files[0]); {#給對象添加鍵是fafafa 值是i1標簽的第一個#} var xhr =new XMLHttpRequest(); {#實例化一個對象#} xhr.onreadystatechange =function () { {#給對象設置一個回調函數#} if (xhr.readyState==4){ {#判斷如果xhr對象的執行數字等於4#} var file_path =xhr.responseText; {#獲取對象的文本信息賦值給file_path responseText是返回文本字符串#} var tag = document.createElement('img'); {#創建一個img標簽,標簽名字是tag#} tag.src='/'+file_path; {#通過標簽名創建一個圖片路徑#} document.getElementById('container1').appendChild(tag); {#通過id找到container1標簽 然后再通過標簽的名添加個子標簽#} } } }; xhr.open('POST','/upload/'); {#對象調用open方法創建一個連接,參數post傳輸方式 /upload/傳輸地址url#} xhr.send(formData); {#通過對象發送FormData實例化的對象#} {#======================================================JQuery Ajax上傳文件======================================#} function upload2() { {#定義一個函數#} var formData =new FormData(); {#通過FornData 實例化一個對象,FormData是個特殊的功能,可以傳輸文件和字符串#} formData.append('k1','v1'); {#給對象添加倆個值鍵是k1 值是v1#} formData.append('fafafa',$('#i2')[0].files[0]); {#把fafafa作為鍵 值是id等於i2的標簽轉換成Dom對象的第一個#} $.ajax({ url:'/upload/', type:'POST', data:formData, contentType:false, {#告訴后端不進行請求頭設置#} processData:false, {#告訴后端不進行請求頭設置#} success:function (arg) { {#回調函數#} var tag =document.createElement('img'); {#創建一個img標簽名稱為tag#} tag.src='/'+arg; {#為名字為tag的標簽設置路徑#} $('#container2').append(tag); {#為id是container2標簽的添加名字是tag的標簽為子標簽#} } }) } function upload3() { {# 定義一個函數#} document.getElementById('ifr').onload=loadIframe; {# 查找id是ifr的標簽並設置在加載時調用loadIframe函數#} document.getElementById('f1').submit(); {#查找id是f1的標簽並啟動#} } function loadIframe() { {#定義一個函數#} var content =document.getElementById('ifr').contentWindow.document.body.innerText; {#查找id是ifr的標簽,的window內容的請求體的文本信息#} var tag = document.createElement('img'); {#創建一個img標簽並設置標簽名字是tag#} tag.src='/'+content; {#找到名字是tag標簽設置路徑#} $('#container3').append(tag); {#找到id 是container3的標簽添加一個名字是tag的標簽tag#} } </script> </body> </html>