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>
