什么是AJAX
AJAX = Asynchronous JavaScript and XML(異步的 JavaScript 和 XML)。
優點:
不重新加載整個頁面的情況下,可以與服務器交換數據并更新部分網頁內容
不需要任何瀏覽器插件,但需要用戶允許JavaScript在瀏覽器上執行
同源策略與jsonp
同源策略(Same origin policy)是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能可能都會受到影響。可以說Web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現。
jsonp(jsonpadding)
之前發ajax的時候都是在自己給自己的當前的項目下發
現在我們來實現跨域發。
ajax請求的本質:生成xmlHttpRequest對象


<!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta http-equiv="x-ua-compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1"><title>index</title><script src="http://cdn.static.runoob.com/libs/jquery/1.10.2/jquery.min.js"></script> </head> <body> <form action="" method="" ><input type="text" name="k1" value="v1"><input type="text" name="k2" value="v2"><input id="forms_btn" type="button" value="提交">{% csrf_token %}</form> <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script></body> </html>
下面是,前端以json格式 發往后端的JavaScript代碼
<script>$("#forms_btn").click(function () {$.ajax({url:"/fromData/",type:"post",dataType:"json", // 注意 :是預期服務器返回的數據類型
headers:{"X-CSRFToken":$("[name='csrfmiddlewaretoken']").val()},contentType:"application/json",data:{"name":$("[name='k1']").val(),"name":$("[name='k2']").val(),},})})
</script>
注意:?
1、設置contentType:默認編碼格式 “url_encoding” ?a=1&b=2
2、設置headers
3、data, 在后端接受到是以二進制形式(b'password=v1&name=v2'),需要反序列化
前端的JavaScript data{“a”:1,“b”:2}, 其中a,b 可以不用提前定義,就使用,所以可以這樣使用:data{a:1,b:2}和Python不同
4、后臺取數據不能在POST中取,需要在body中取
dataType
前端設置dataType ,后端如果返回的非json數據,后端不能識別,但是不報錯,
使用Ajax跨域
view層
def ajax_send(request):func=request.GET.get("callback")print("func",func)res={"name":"alex"}import jsonreturn HttpResponse("%s('%s')"%(func,json.dumps(res)))
ajax 無法跨域訪問其他網站,
<script>$(".b1").click(function () {$.ajax({url:"http://127.0.0.1:8002/ajax_send/", // 瀏覽器的同源策略的原因,AJax無法發送跨域請求 success:function (data) {alert(data)}})}); </script>
下面看如何解決跨域訪問
跨域訪問初級版
<script>function foo(s) {console.log(s);JSON.parse(s)}function kua_yu(url) {// 生成 script標簽var $ele_script=$("<script>"); 注意:使用了 $ele_script創建標簽$ele_script.attr("src",url);$ele_script.attr("class","kuayu");// 添加到body中 $("body").append($ele_script); // 發送請求 $(".kuayu").remove() // 生成之后即刪除,不會產生多余的標簽}$(".b2").click(function () {kua_yu( "http://127.0.0.1:8002/ajax_send/?callback=foo")}); </script>
跨域訪問進階版
$(".b1").click(function () {$.getJSON("http://127.0.0.1:8002/ajax_send/?callback=?",function (data) { // function 使用了回調函數,console.log(data);})
});
要注意的是在url的后面必須添加一個callback參數,這樣getJSON方法才會知道是用JSONP方式去訪問服務,callback后面的那個?是內部自動生成的一個回調函數名
跨域訪問高級版
<script> $(".b1").click(function () {$.ajax({url:'http://127.0.0.1:8002/ajax_send/',dataType:"jsonp",jsonp: 'callback',jsonpCallback:"SayHi"}); });$(".b2").click(function () {$.ajax({url:'http://www.jxntv.cn/data/jmd-jxtv2.html?',dataType:"jsonp",jsonp: 'callback',jsonCallback:"list" // 訪問的函數名,可定制});});function list(data) {console.log(data.data);$.each(data.data,function (i,weekday) {//console.log(j); // {week: "周日", list: Array(19)} $("body").append("<p>"+weekday.week+"</p>");console.log(weekday.list);$.each(weekday.list,function (j,show) {s="<p><a href='"+show.link+"'>"+show.name+"</a></p>"$("body").append(s);})})}</script>
注意:jsonp 一定是GET請求
csrf跨站請求偽造
如果把type:"GET"? 改為type:"POST" 會報一個Forbidden的錯
解決辦法有三種:
方式一:
$.ajaxSetup({data:{csrfmiddlewaretoken:'{{ csrf_token }}'}});注意:要放在ajax請求的前面,在發送之前組裝一組字符串,在第一步render的時候就發了所以有局限性:如果把JS代碼放到靜態文件中,不會渲染,不會執行{{csrf_token}},只能在HTML頁面中使用
方式二:自己組裝一組鍵值對? ( 推薦)
<form>
{% csrf_token %}
</form>data:{csrfmiddlewaretoken:$("[name='csrfmiddlewaretoken']").val(),name:$(":text").val(),pwd:$(":password").val()},
方式三:自己設置頭信息
<script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script>
$.ajax({url:"/serialize/",type:"POST",headers:{"X-CSRFToken":$.cookie('csrftoken')},})
jQuery.serialize()?
serialize()
函數用于序列化一組表單元素,將表單內容編碼為用于提交的字符串。
serialize()
函數常用于將表單內容序列化,以便用于AJAX提交。
該函數主要根據用于提交的有效表單控件的name和value,將它們拼接為一個可直接用于表單提交的文本字符串,該字符串已經過標準的URL編碼處理(字符集編碼為UTF-8)。
該函數不會序列化不需要提交的表單控件,這和常規的表單提交行為是一致的。例如:不在<form>標簽內的表單控件不會被提交、沒有name屬性的表單控件不會被提交、帶有disabled屬性的表單控件不會被提交、沒有被選中的表單控件不會被提交。
與常規表單提交不一樣的是:常規表單一般會提交帶有name的按鈕控件,而serialize()函數不會序列化帶有name的按鈕控件。更多詳情請點擊這里。
語法:
jQueryObject.serialize( )
serialize()
函數的返回值為String類型,返回將表單元素編碼后的可用于表單提交的文本字符串。
請參考下面這段初始HTML代碼:
<form name="myForm" action="http://www.365mini.com" method="post"><input name="uid" type="hidden" value="1" /><input name="username" type="text" value="張三" /><input name="password" type="text" value="123456" /><select name="grade" id="grade"><option value="1">一年級</option><option value="2">二年級</option><option value="3" selected="selected">三年級</option><option value="4">四年級</option><option value="5">五年級</option><option value="6">六年級</option></select><input name="sex" type="radio" checked="checked" value="1" />男<input name="sex" type="radio" value="0" />女<input name="hobby" type="checkbox" checked="checked" value="1" />游泳<input name="hobby" type="checkbox" checked="checked" value="2" />跑步<input name="hobby" type="checkbox" value="3" />羽毛球<input name="btn" id="btn" type="button" value="點擊" /> </form>
?對<form>元素進行序列化可以直接序列化其內部的所有表單元素。
// 序列化<form>內的所有表單元素 // 序列化后的結果:uid=1&username=%E5%BC%A0%E4%B8%89&password=123456&grade=3&sex=1&hobby=1&hobby=2 alert( $("form").serialize() );
我們也可以直接對部分表單元素進行序列化。
// 序列化所有的text、select、checkbox表單元素 // 序列化后的結果:username=%E5%BC%A0%E4%B8%89&password=123456&grade=3&hobby=1&hobby=2 alert( $(":text, select, :checkbox").serialize() );
示例:


<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width"><title>Title</title> </head> <body> <form name="myForm" action="http://www.365mini.com" method="post"><input name="uid" type="hidden" value="1" /><input name="username" type="text" value="張三" /><input name="password" type="text" value="123456" /><select name="grade" id="grade"><option value="1">一年級</option><option value="2">二年級</option><option value="3" selected="selected">三年級</option><option value="4">四年級</option><option value="5">五年級</option><option value="6">六年級</option></select><input name="sex" type="radio" checked="checked" value="1" />男<input name="sex" type="radio" value="0" />女<input name="hobby" type="checkbox" checked="checked" value="1" />游泳<input name="hobby" type="checkbox" checked="checked" value="2" />跑步<input name="hobby" type="checkbox" value="3" />羽毛球<input name="btn" id="btn" type="button" value="點擊" /> </form> <script src="/static/jquery-3.2.1.min.js"></script> <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script> <script>$("#btn").click(function () { {# 方式一#}//$.ajaxSetup({// data:{csrfmiddlewaretoken:'{{ csrf_token }}'}//}); $.ajax({url:"/serialize/",type:"POST", {# 方式三#}headers:{"X-CSRFToken":$.cookie('csrftoken')},//data:$("form").serialize(), //序列form表單所有的 data:$(":text,:password,:checkbox").serialize(), //序列自己選擇的 success:function (data) {var data=JSON.parse(data); //js中的反序列化 console.log(data);console.log(typeof data);$(".error").html(data);}})}) </script> </body> </html>serialize.html


1 def serialize(request): 2 # form = request.POST 3 # print(form) 4 name = request.POST.get("username") 5 password = request.POST.get("password") 6 checked = request.POST.getlist("hobby") 7 print(name,password,checked) 8 return HttpResponse(json.dumps(name))
當有好多input的時候,就得一一對應的吧所有的數據發過去的,這樣顯得麻煩,我們用序列化 jQuery.serialize()data:$("form").serialize(), //序列form表單所有的 data:$(":text,:password,:checkbox").serialize(), //序列自己選擇的在服務端獲取數據 form = request.POST print(form) #獲取所有 name = request.POST.get("username") password = request.POST.get("password") checked = request.POST.getlist("hobby") print(name,password,checked)#獲取單個
?Ajax上傳文件(利用FormData)
既可以處理二進制,又可以處理字典,列表啊等
FormData是什么呢?
FormData
.利用FormData對象
,我們可以通過JavaScript用一些鍵值對來模擬一系列表單控件,我們還可以使用XMLHttpRequest的send()
方法來異步的提交這個"表單".比起普通的ajax,使用FormData
的最大優點就是我們可以異步上傳一個二進制文件.$("#upload") 拿到的是一個集合 $("#upload")[0] 就是一個dom對象 $("#upload")[0].files 拿到的是一個filelist $("#upload")[0].files[0] 拿到的是當前最近的文件對象
要是使用FormData一定要加上:
一定要加上:
contentType:false?
processDate:false #不做預處理
ajaxupload.html
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width"><title>Title</title> </head> <body> <p>姓名<input type="text" name="username"></p> <p>頭像<input type="file" id="upload"></p> <p><button class="btnnn">提交</button><span class="tishi"></span></p> <script src="/static/jquery-3.2.1.min.js"></script> <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script> <script>$(".btnnn").click(function () {var formData=new FormData();formData.append("username",$(":text").val());formData.append("file",$("#upload")[0].files[0]);$.ajax({url:"/get_upload/",type:"POST",headers:{"X-CSRFToken":$.cookie('csrftoken')},data:formData,contentType:false,processData:false,success:function (data) {$(".tishi").html("上傳成功")}})}) </script> </body> </html>
?view.py
def ajaxupload(request):return render(request,"ajaxupload.html")def get_upload(request):if request.method == "POST":print("FIFLE", request.FILES)file_obj = request.FILES.get("file")print(file_obj.name, "-----")file_obj = request.FILES.get("file")with open(file_obj.name, "wb") as f:for i in file_obj:f.write(i)return HttpResponse("上傳成功")
?