07 django與ajax
什麼是 JSON ?
-
JSON 指的是 JavaScript 物件表示法(JavaScript Object Notation)
-
JSON 是輕量級的文字資料交換格式
-
JSON 獨立於語言 *
-
JSON 具有自我描述性,更易理解
* JSON 使用 JavaScript 語法來描述資料物件,但是 JSON 仍然獨立於語言和平臺。JSON 解析器和 JSON 庫支援許多不同的程式語言。
啥都別多說了,上圖吧!
合格的json物件(json只認雙引的字串格式):
["one", "two", "three"]
{ "one": 1, "two": 2, "three": 3 }
{"names": ["張三", "李四"] }
[ { "name": "張三"}, {"name": "李四"} ]
不合格的json物件:
{ name: "張三", 'age': 32 } // 屬性名必須使用雙引號
[32, 64, 128, 0xFFF] // 不能使用十六進位制值
{ "name": "張三", "age": undefined } // 不能使用undefined
{ "name": "張三",
"birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),
"getName": function() {return this.name;} // 不能使用函式和日期物件
}
stringify與parse方法
JavaScript中關於JSON物件和字串轉換的兩個方法:
JSON.parse(): 用於將一個 JSON 字串轉換為 JavaScript 物件(json只認雙引的字串格式)
JSON.parse('{"name":"Howker"}');
JSON.parse('{name:"Stack"}') ; // 錯誤
JSON.parse('[18,undefined]') ; // 錯誤
JSON.stringify(): 用於將 JavaScript 值轉換為 JSON 字串。
JSON.stringify({"name":"Tonny"})
和XML的比較
JSON 格式於2001年由 Douglas Crockford 提出,目的就是取代繁瑣笨重的 XML 格式。
JSON 格式有兩個顯著的優點:書寫簡單,一目瞭然;符合 JavaScript 原生語法,可以由解釋引擎直接處理,不用另外新增解析程式碼。所以,JSON迅速被接受,已經成為各大網站交換資料的標準格式,並被寫入ECMAScript 5,成為標準的一部分。
XML和JSON都使用結構化方法來標記資料,下面來做一個簡單的比較。
用XML表示中國部分省市資料如下:
用JSON表示如下:
{
"name": "中國",
"province": [{
"name": "黑龍江",
"cities": {
"city": ["哈爾濱", "大慶"]
}
}, {
"name": "廣東",
"cities": {
"city": ["廣州", "深圳", "珠海"]
}
}, {
"name": "臺灣",
"cities": {
"city": ["臺北", "高雄"]
}
}, {
"name": "新疆",
"cities": {
"city": ["烏魯木齊"]
}
}]
}
由上面的兩端程式碼可以看出,JSON 簡單的語法格式和清晰的層次結構明顯要比 XML 容易閱讀,並且在資料交換方面,由於 JSON 所使用的字元要比 XML 少得多,可以大大得節約傳輸資料所佔用得頻寬。
AJAX簡介
AJAX(Asynchronous Javascript And XML)翻譯成中文就是“非同步的Javascript和XML”。即使用Javascript語言與伺服器進行非同步互動,傳輸的資料為XML(當然,傳輸的資料不只是XML)。
AJAX 不是新的程式語言,而是一種使用現有標準的新方法。
AJAX 最大的優點是在不重新載入整個頁面的情況下,可以與伺服器交換資料並更新部分網頁內容。(這一特點給使用者的感受是在不知不覺中完成請求和響應過程)
AJAX 不需要任何瀏覽器外掛,但需要使用者允許JavaScript在瀏覽器上執行。
-
同步互動:客戶端發出一個請求後,需要等待伺服器響應結束後,才能發出第二個請求;
-
非同步互動:客戶端發出一個請求後,無需等待伺服器響應結束,就可以發出第二個請求。
示例
*頁面輸入兩個整數,通過AJAX傳輸到後端計算出結果並返回。*
html部分程式碼
views.py
def ajax_test(request):
if request.method=='POST':
i1=request.POST.get('i1')
i2=request.POST.get('i2')
ret=int(i1)+int(i2)
return HttpResponse(ret)
return render(request,'ajax_test.html')
urls.py
from django.conf.urls import url from app01 import views urlpatterns=[ url(r'^ajax_test/',views.ajax_test), ]
AJAX常見應用情景
搜尋引擎根據使用者輸入的關鍵字,自動提示檢索關鍵字。
還有一個很重要的應用場景就是註冊時候的使用者名稱的查重。
其實這裡就使用了AJAX技術!當檔案框發生了輸入變化時,使用AJAX技術向伺服器傳送一個請求,然後伺服器會把查詢到的結果響應給瀏覽器,最後再把後端返回的結果展示出來。
-
整個過程中頁面沒有重新整理,只是重新整理頁面中的區域性位置而已!
-
當請求發出後,瀏覽器還可以進行其他操作,無需等待伺服器的響應!
當輸入使用者名稱後,把游標移動到其他表單項上時,瀏覽器會使用AJAX技術向伺服器發出請求,伺服器會查詢名為lemontree7777777的使用者是否存在,最終伺服器返回true表示名為lemontree7777777的使用者已經存在了,瀏覽器在得到結果後顯示“使用者名稱已被註冊!”。
-
整個過程中頁面沒有重新整理,只是區域性重新整理了;
-
在請求發出後,瀏覽器不用等待伺服器響應結果就可以進行其他操作;
AJAX的優缺點
優點:
-
AJAX使用JavaScript技術向伺服器傳送非同步請求;
-
AJAX請求無須重新整理整個頁面;
-
因為伺服器響應內容不再是整個頁面,而是頁面中的部分內容,所以AJAX效能高;
-
兩個關鍵點:1.區域性重新整理,2.非同步請求
jQuery實現的AJAX
最基本的jQuery傳送AJAX請求示例:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <style> .hide { display: none; } </style> </head> <body> <p><input type="text" class="user"><span class="hide" style="color: red">使用者名稱已存在</span></p> <script src="/static/jquery-3.3.1.min.js"></script> {#下面這一項是基於jQuery的基礎上自動給我們的每一個ajax繫結一個請求頭資訊,類似於form表單提交post資料必須要有的csrf_token一樣#} {#否則我的Django中介軟體裡面的校驗csrf_token那一項會認為你這個請求不是合法的,阻止你的請求#} <script src="/static/setup_Ajax.js"></script> <script> //給input框繫結一個失去焦點的事件 $('.user').blur(function () { //$.ajax為固定用法,表示啟用ajax $.ajax({ //url後面跟的是你這個ajax提交資料的路徑,向誰提交,不寫就是向當前路徑提交 url:'', //type為標定你這個ajax請求的方法 type:'POST', //data後面跟的就是你提交給後端的資料 data:{'username':$(this).val()}, //success為回撥函式,引數data即後端給你返回的資料 success:function (data) { ret=JSON.parse(data); if (ret['flag']){ $('p>span').removeClass('hide'); } } }) }); </script> </body> </html>
views.py:
def index(request): if request.method=='POST': ret={'flag':False} username=request.POST.get('username') if username=='JBY': ret['flag']=True import json return HttpResponse(json.dumps(ret)) return render(request,'index.html')
$.ajax引數
data引數中的鍵值對,如果值值不為字串,需要將其轉換成字串型別。
$("#b1").on("click", function () { $.ajax({ url:"/ajax_add/", type:"GET", data:{"i1":$("#i1").val(),"i2":$("#i2").val(),"hehe": JSON.stringify([1, 2, 3])}, success:function (data) { $("#i3").val(data); } }) })
JS實現AJAX(瞭解)
var b2 = document.getElementById("b2"); b2.onclick = function () { // 原生JS var xmlHttp = new XMLHttpRequest(); xmlHttp.open("POST", "/ajax_test/", true); xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlHttp.send("username=q1mi&password=123456"); xmlHttp.onreadystatechange = function () { if (xmlHttp.readyState === 4 && xmlHttp.status === 200) { alert(xmlHttp.responseText); } }; };
AJAX請求如何設定csrf_token
不論是ajax還是誰,只要是向我Django提交post請求的資料,都必須校驗csrf_token來防偽跨站請求,那麼如何在我的ajax中弄這個csrf_token呢,我又不像form表單那樣可以在表單內部通過一句{% csrf_token %}就搞定了......
方式1
通過獲取隱藏的input標籤中的csrfmiddlewaretoken值,放置在data中傳送。
$.ajax({ url: "/cookie_ajax/", type: "POST", data: { "username": "Tonny", "password": 123456, "csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val() // 使用JQuery取出csrfmiddlewaretoken的值,拼接到data中 }, success: function (data) { console.log(data); } })
方式2
通過獲取返回的cookie中的字串 放置在請求頭中傳送。
注意:需要引入一個jquery.cookie.js外掛。
$.ajax({ url: "/cookie_ajax/", type: "POST", headers: {"X-CSRFToken": $.cookie('csrftoken')}, // 從Cookie取csrf_token,並設定ajax請求頭 data: {"username": "Q1mi", "password": 123456}, success: function (data) { console.log(data); } })
方式3
或者用自己寫一個getCookie方法:
function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie !== '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrftoken = getCookie('csrftoken');
每一次都這麼寫太麻煩了,可以使用$.ajaxSetup()方法為ajax請求統一設定。
function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } });
將下面的檔案配置到你的Django專案的靜態檔案中,在html頁面上通過匯入該檔案即可自動幫我們解決ajax提交post資料時校驗csrf_token的問題,(匯入該配置檔案之前,需要先匯入jQuery,因為這個配置檔案內的內容是基於jQuery來實現的)
更多細節詳見:
練習(使用者名稱是否已被註冊)
功能介紹
在登錄檔單中,當用戶填寫了使用者名稱後,把游標移開後,會自動向伺服器傳送非同步請求。伺服器返回這個使用者名稱是否已經被註冊過。
案例分析
-
頁面中給出登錄檔單;
-
在username input標籤中繫結onblur事件處理函式。
-
當input標籤失去焦點後獲取 username表單欄位的值,向服務端傳送AJAX請求;
-
django的檢視函式中處理該請求,獲取username值,判斷該使用者在資料庫中是否被註冊,如果被註冊了就返回“該使用者已被註冊”,否則響應“該使用者名稱可以註冊”。
答案就在前面的示例中,看你能不能找到了......
序列化
Django內建的serializers
什麼意思呢?就是我的前段想拿到由ORM得到的資料庫裡面的一個個使用者物件,我的後端想直接將例項化出來的資料物件直接傳送給客戶端,那麼這個時候,就可以用Django給我們提供的序列化方式
def ser(request): #拿到使用者表裡面的所有的使用者物件 user_list=models.User.objects.all() #匯入內建序列化模組 from django.core import serializers #呼叫該模組下的方法,第一個引數是你想以什麼樣的方式序列化你的資料 ret=serializers.serialize('json',user_list) return HttpResponse(ret)
補充一個SweetAlert外掛示例
點選下載
$("#b55").click(function () { swal({ title: "你確定要刪除嗎?", text: "刪除可就找不回來了哦!", type: "warning", showCancelButton: true, // 是否顯示取消按鈕 confirmButtonClass: "btn-danger", // 確認按鈕的樣式類 confirmButtonText: "刪除", // 確認按鈕文字 cancelButtonText: "取消", // 取消按鈕文字 closeOnConfirm: false, // 點選確認按鈕不關閉彈框 showLoaderOnConfirm: true // 顯示正在刪除的動畫效果 }, function () { var deleteId = 2; $.ajax({ url: "/delete_book/", type: "post", data: {"id": deleteId}, success: function (data) { if (data.code === 0) { swal("刪除成功!", "你可以準備跑路了!", "success"); } else { swal("刪除失敗", "你可以再嘗試一下!", "error") } } }) }); })
上面這個二次確認的動態框樣式,你也可以直接應用到你的專案中
提醒事項:
1.上述的樣式類部分渲染的樣式來自於bootstrap中,所有建議在使用上述樣式時,將bootstrap的js和css也匯入了,這樣的情況下,頁面效果就不會有任何問題
2.彈出的上述模態框中,可能字型會被圖示掩蓋一部分,可通過調整字型的上外邊距來解決