Django中操作AJAX
文章目錄
補充Django內建的兩個裝飾器方法:
from django.views.decorators.csrf import csrf_exempt, csrf_protect
# csrf_exempt:給指定檢視排除csrf校驗 csrf_exempt:指定某個檢視必須csrf校驗
使用ensure_csrf_cookie()裝飾器可以強制設定csrf到Cookie:
django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def login(request):
pass
DJango內建的序列化方法:
from django.core import serializers
def user_list(request):
user_list = models.Userinfo.objects.all()
ret = serializers.serialize('json', user_list)
return HttpResponse(ret)
JSON
什麼是JSON?
- JSON指的是JavaScript物件表示法(JavaScript Object Notation)
- JSON是輕量級的文字資料交換格式
- JSON獨立於語言
- JSON具有自我描述性,更易理解
JSON使用JavaScript語法來描述資料物件,但是JSON仍然獨立於語言和平臺。JSON直譯器和JSON庫支援許多不同的程式語言.
合格的json物件:
['one', 'two', 'three']
{'one': 1, 'two': 2, 'three': 3}
{'users': ['zyk01', 'zyk02']}
[{'user': 'zyk'}, {'sex': 'boy'}]
不合格的json物件:
"""屬性名必須使用引號(反序列化後是雙引號)"""
{name: 'zyk', 'sex': 'oby'}
"""不能使用十六進位制值"""
[16, 32, 64, 128, 0xFFF]
"""不能使用undefined"""
{'name': 'zyk', 'age': undefined}
"""不能使用日期物件"""
{'name': 'zyk', 'birthday': new Date('Fri, 26 Aug 2011 07:13:10 GMT'
"""不能使用函式"""
{'getName': function() {return this.name;}, 'sex': 'boy'}
序列化 stringify
JavaScript中使用JSON的stringily方法進行序列化
反序列化 parse
JavaScript中使用JSON的parse方法進行反序列化
JSON與XML對比
JSON格式於2001年由Douglas Crockford提出,目的就是取代繁瑣笨重的XML格式。
JSON格式有兩個顯著的優點:書寫簡單、一目瞭然;符合JavaScript原生語法,可以由解釋引擎直接處理,不用另外新增解析程式碼。
因此,JSON迅速被接受,已經成為各大網路交換資料的標準格式,並被寫入ECMAScript 5,成為標準的一部分。
對比:
用XML表示中國部分省市資料如下:
<?xml version="1.0" encoding="utf-8"?>
<country>
<name>中國</name>
<province>
<name>黑龍江</name>
<cities>
<city>哈爾濱</city>
<city>大慶</city>
</cities>
</province>
<province>
<name>廣東</name>
<cities>
<city>廣州</city>
<city>深圳</city>
<city>珠海</city>
</cities>
</province>
<province>
<name>臺灣</name>
<cities>
<city>臺北</city>
<city>高雄</city>
</cities>
</province>
<province>
<name>新疆</name>
<cities>
<city>烏魯木齊</city>
</cities>
</province>
</country>
用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頁面程式碼:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta http-equiv="content-Type" charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="/static/jquery-3.3.1.js"></script>
<title>AJAX區域性重新整理例項</title>
</head>
<body>
<input type="text" id="sign01"> +
<input type="text" id="sign02"> =
<input type="text" id="sign03">
<input type="button" value="計算" id="tag">
<script>
$('#tag').click(function () { {# 'click'是滑鼠點選事件 #}
$.ajax({
url: '/ajax_add/', {# 請求的url地址 #}
type: 'GET', {# 請求方式 #}
'data': {
sign01: $('#sign01').val(),
'sign02': $('#sign02').val()
}, {# 傳送的資料 #}
success: function (res) {
$('#sign03').val(res);
}, {# 回撥函式(執行成功時被呼叫) res:返回的資料 #}
});
});
{# 裡面所有的key都可以寫成字串 #}
</script>
</body>
</html>
檢視頁面程式碼:
from django.shortcuts import render
from django.http import JsonResponse
def ajax_demol(request):
return render(request, 'ajax_demol.html')
# 計算功能
def ajax_add(request):
sign01 = request.GET.get('sign01')
sign02 = request.GET.get('sign02')
sign03 = int(sign01) + int(sign02)
return JsonResponse(sign03, safe=False)
# JsonResponse方法預設只允許序列化dict型別的資料.
# safe=False:將安全引數設定為False後,才可允許序列化非dict型別的資料.
urls頁面配置:
from century01 import views
urlpatterns = [
url(r'^ajax_demol/$', views.ajax_demol),
url(r'^ajax_add/$', views.ajax_add),
]
AJAX常見應用場景
搜尋引擎根據使用者輸入的關鍵字,自動提示檢索關鍵字。
還有一個很重要的應用場景就是註冊時使用者名稱的檢視。
其實這裡就使用了AJAX技術,當檔案框發生輸入變化時,使用AJAX技術向伺服器傳送一個請求,然後伺服器會把查詢到的結果響應給瀏覽器,最後再把後端返回的結果展示出來。
- 整個過程中頁面沒有重新整理,只是重新整理頁面中的區域性位置而已.
- 當請求發出後,瀏覽器還可以進行其它操作,無需等待伺服器的響應.
當輸入使用者名稱後,把游標移動到其他表單項上時,瀏覽器會使用AJAX技術向伺服器發出請求,伺服器會查詢名為lemontree7777777的使用者是否存在,最終伺服器返回true表示名為lemontree7777777的使用者已經存在了,瀏覽器在得到結果後顯示“使用者名稱已被註冊!”。
- 整個過程中頁面沒有重新整理,只是區域性重新整理了.
- 在請求發出後,瀏覽器不用等待伺服器響應結果就可以進行其它操作.
AJAX的優點
- AJAX使用JavaScript技術向伺服器傳送非同步請求;
- AJAX請求無需重新整理整個頁面;
- 因為伺服器響應內容不再是整個頁面,而是頁面中的部分內容,所以AJAX效能高;
$.ajax的引數
<script>
$('#sign').on('click', function () { {# 'click'是滑鼠點選事件 #}
$.ajax({
{# 請求的URL地址 #}
url: '/ajax_test/',
{# 請求的型別 #}
type: 'POST',
{# 要傳送的資料 #}
data: {
'name': 'zyk',
{# 如果不是字串則需要序列化 #}
'hobby': JSON.stringify(['AJAX', 'Django', 'Python']),
},
{# 回撥函式(成功時執行) data:伺服器返回的資料 #}
success: function (data) {
$('#sign00').val(data);
},
{# 回撥函式(出錯時執行) data:伺服器返回的資料 #}
error: function (data) {
alert('error');
},
});
});
</script>
jQuery實現AJAX
最基本的jQuery傳送AJAX請求示例:
HTML檔案程式碼:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta http-equiv="content-Type" charset="UTF-8">
<meta http-equiv="x-ua-compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="/static/jquery-3.3.1.js"></script>
<title>AJAX 測試</title>
</head>
<body>
<button id="ajaxTest">AjAX 測試</button>
<script>
$('#ajaxTest').click(function () { {# 'click'是滑鼠點選事件 #}
$.ajax({
url: '/ajax_test/', {# 請求的url地址 #}
type: 'POST', {# 請求的方式 #}
data: {
user: 'zyk',
pwd: '[email protected]',
}, {# 傳送的資料 #}
success: function (data) {
{# 彈出警告框 #}
alert(data)
}, {# 回撥函式(執行成功時被呼叫) data:返回的資料 #}
});
});
</script>
</body>
</html>
檢視檔案程式碼:
from django.shortcuts import render, HttpResponse
from century01 import models
def ajax_test(request):
if request.method == 'POST':
user = request.POST.get('user')
pwd = request.POST.get('pwd')
ret = 'is ok' if models.Userinfo.objects.filter(name=user, pwd=pwd) else 'is no'
return HttpResponse(ret)
return render(request, 'ajax_test.html')
JS實現AJAX
<script>
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);
}
};
};
</script>
AJAX請求設定csrf_token
檢視檔案程式碼如下:
from django.shortcuts import render, HttpResponse
from century01 import models
def ajax_test(request):
if request.method == 'POST':
user = request.POST.get('user')
pwd = request.POST.get('pwd')
ret = 'is ok' if models.Userinfo.objects.filter(name=user, pwd=pwd) else 'is no'
return HttpResponse(ret)
return render(request, 'ajax_test.html')
方法一
通過獲取隱藏的input標籤中的csrfmiddlewaretoken的值,放到data中傳送.
<body>
{% csrf_token %}
<button id="ajaxTest">AjAX 測試</button>
<script>
$('#ajaxTest').click(function () {
$.ajax({
url: '/ajax_test/', {# 請求的url地址 #}
type: 'POST', {# 請求的方式 #}
data: {
user: 'zyk',
pwd: '[email protected]',
// 獲取隱藏的input標籤中的csrfmiddlewaretoken的值
csrfmiddlewaretoken: $("[name = 'csrfmiddlewaretoken']").val()
}, {# 傳送的資料 #}
success: function (data) {
{# 彈出警告框 #}
alert(data);
}, {# 回撥函式(執行成功時被呼叫) data:返回的資料 #}
});
});
</script>
</body>
方法二
通過獲取隱藏的input標籤中的csrfmiddlewaretoken的值,放置在請求頭中傳送.
<body>
{% csrf_token %}
<button id="ajaxTest">AjAX 測試</button>
<script>
$('#ajaxTest').click(function () {
$.ajax({
url: '/ajax_test/',
type: 'POST',
// 獲取隱藏的input標籤中的csrfmiddlewaretoken的值
headers: {'X-CSRFToken': $('[name="csrfmiddlewaretoken"]').val(),},
data: {
user: 'zyk',
pwd: '[email protected]'},
success: function (data) {
alert(data);
},
});
});
</script>
</body>
方法三
或者自己寫一個getCookie方法的js檔案(直接複製):
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');
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);
}
}
});
然後在網頁檔案中直接匯入上面的js檔案即可:
<body>
{% csrf_token %}
<button id="ajaxTest">AjAX 測試</button>
// 匯入上面的檔案:
<script src="/static/ajax_setup.js"></script>
<script>
$('#ajaxTest').click(function () {
$.ajax({
url: '/ajax_test/',
type: 'POST',
data: {
user: 'zyk',
pwd: '[email protected]'},
success: function (data) {
alert(data);
},
});
});
</script>
</body>
注意:
如果使用從cookie中取csrftoken的方式(本文中未使用),需要確保cookie存在csrftoken值。
如果你的檢視渲染的HTML檔案中沒有包含 {% csrf_token %},Django可能不會設定CSRFtoken的cookie。
這個時候需要使用ensure_csrf_cookie()裝飾器強制設定csrf到Cookie: