在此以前你必定須要先學習下JavaScript JSON 可見:html
咱們之前知道的前端向後端發送數據的方式有:jquery
GET:地址欄、a標籤、Form表單ajax
POST:Form表單chrome
那麼如今咱們在學習一種:那就是ajaxdjango
ajax:也是前端向後端發送數據的一種方式json
AJAX(Asynchronous Javascript And XML)翻譯成中文就是「異步Javascript和XML」。即便用Javascript語言與服務器進行異步交互,傳輸的數據爲XML(固然,傳輸的數據不僅是XML)。後端
AJAX(Asynchronous Javascript And XML)翻譯成中文就是「異步Javascript和XML」。即便用Javascript語言與服務器進行異步交互,傳輸的數據爲XML(固然,傳輸的數據不僅是XML,如今更多使用json數據)。瀏覽器
同步交互:客戶端發出一個請求後,須要等待服務器響應結束後,才能發出第二個請求;服務器
異步交互:客戶端發出一個請求後,無需等待服務器響應結束,就能夠發出第二個請求。
Ajax的特色(優勢):
異步交互: 當請求發出後,瀏覽器還能夠進行其餘操做,無需等待服務器的響應!
局部刷新: 整個過程當中頁面沒有刷新,只是刷新頁面中的局部位置而已!
二.jQuery實現Ajax
前提是在Django框架上,並已經作相關的基礎配置後。
前端代碼:
<body> {% csrf_token %} <p><input type="text" class="user" placeholder="用戶名"></p> <p><input type="password" placeholder="密碼" class="pwd"></p> <button id="ajaxTest">AJAX 測試</button> <script src="/static/js/jquery.js"></script> <script> $("#ajaxTest").click(function () { var username = $(".user").val(); var password = $(".pwd").val(); console.log(username, password); $.ajax({ url: "/jq_ajax/", type: "POST", data: { csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(), user: username, pwd: password, }, success: function (res) { alert("hahaha") //將來接收服務端返回值,來進行作判斷作的相應的反應 if (res == "ok"){ alert("okla") }else{ alert("buok.") } } }) }) </script> </body>
後端代碼:
def jq_ajax(request): # if request.method == "GET": if request.is_ajax(): username = request.POST.get("user") password = request.POST.get("pwd") print(username, password) return HttpResponse("okddd") return render(request, "jq_ajax.html")
在註冊表單中,當用戶填寫了用戶名後,把光標移開後,會自動向服務器發送異步請求。服務器返回true或false,返回true表示這個用戶名已經被註冊過,返回false表示沒有註冊過。客戶端獲得服務器返回的結果後,肯定是否在用戶名文本框後顯示「用戶名已被註冊」的錯誤信息!
用戶在表單輸入要註冊用戶名,用戶單擊框外,網頁經過Ajax提交給服務器,服務器驗證用戶名是否存在後返回響應信息,客戶端經過響應信息作出相應的提醒,能夠註冊不提醒,不然在頁面上顯示登陸用戶名已經被使用!
前端代碼爲:
<body>
<h3>計算案例</h3>
{% csrf_token %}
<input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3"> <button id="btn1">計算</button>
<span id="err"></span>
<script src="/static/js/jquery.js"></script>
<script>
$("#btn1").click(function () {
var i1 = $("#i1").val()
var i2 = $("#i2").val()
$.ajax(
{
url:"/add_test/",
type: "post",
data:{
csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),
i1:i1,
i2:i2,
},
success : function (ret) {
{#var ret = JSON.parse(ret); //在django後端用的是JsonResponse就不用反序列化了#}
console.log(ret,typeof ret);
if (ret.status){
$("#i3").val(ret.msg);
}else {
$("#err").text(ret.msg);
// 過三秒後自動消失
setTimeout(function () {
$("#err").text("");
},3000)
}
{#$("#i3").val(res)#}
}
}
)
})
</script>
</body>
後端django視圖函數爲:
from django.http import JsonResponse
import json
def add_test(request):
if request.is_ajax():
ret = {"status": 1, "msg": None}
num1 = request.POST.get("i1")
num2 = request.POST.get("i2")
try:
res = int(num1) + int(num2)
ret['msg'] = res
except ValueError as e:
ret['status'] = 0
ret['msg'] = "請覈對輸入的數據的合法性"
# return HttpResponse(json.dumps(ret))
//若是用到 JsonResponse就不須要序列化了
return JsonResponse(ret)
return render(request, "add_test.html")
<body>
{% csrf_token %}
<h3>json 數據</h3>
<p><input type="text" class="user" placeholder="用戶名"></p>
<p><input type="password" placeholder="密碼" class="pwd"></p>
<button id="ajaxTest">AJAX json 測試</button>
<script src="/static/js/jquery.js"></script>
<script>
$("#ajaxTest").click(function () {
var user = $(".user").val();
var pwd = $('.pwd').val();
$.ajax({
url: "",
type: 'POST',
//注意T大寫
contentType: "json",
headers: {"X-CSRFToken": $("input[name='csrfmiddlewaretoken']").val()}, // 在請求頭中添加csrf
// json 前端的序列化方式
data: JSON.stringify({
user: user,
pwd: pwd,
{#csrfmiddlewaretoken: $("input[name='csrfmiddlewaretoken']").val(),#}
}),
success: function (ret) {
console.log(ret)
}
})
})
</script>
</body>
def json_test(request):
if request.is_ajax():
print(request.POST) # json時,post爲空
print(request.body) # 若是前端沒有序列化就是原生請求體內容,若是序列化的就是字典(實際上是byte類型)
data_str = request.body.decode()
data = json.loads(data_str)
print(data, type(data)) # 是字典類型
# print(data.get('user'), type(data))
return HttpResponse("ok")
return render(request, "json_test.html")
總結:
前端:
$.ajax({
url: "", # 默認往當前url提交
type: "post", #請求方式
contentType: "json",
headers: {"X-CSRFToken": $("input[name='csrfmiddlewaretoken']").val()}, // 在請求頭中添加csrf
data: JSON.stringify({
key1: val1,
key2: val2,
...
},
success: function(ret){
console.log(ret)
}
})
後端:
request.POST # 爲空
request.body # b'{"user":"alex","pwd":"123"}'
1. 轉換成字符串
2. 反序列化 # dict1 = json.loads(request.body.decode())
<body> <h3>文件上傳</h3> <form action="" method="post" enctype="multipart/form-data"> {% csrf_token %} <input type="file" name="f_name"> <input type="submit" value="上傳"> </form> </body>
import os
def upload(request):
if request.method == "GET":
return render(request, 'upload.html')
else:
print(request.POST) # <class 'str'> 沒有意義
# print(request.body) # enctype="multipart/form-data" ,會報錯
print(request.FILES.get('f_name'), type(request.FILES.get('f_name')))
# 類型是一個對象
file_obj = request.FILES.get('f_name')
print(file_obj.name)
with open(os.path.join("media",file_obj.name),mode="wb") as fp:
for i in file_obj:
fp.write(i)
return HttpResponse("ok")
<body>
<h3>ajax 文件上傳</h3>
{% csrf_token %}
<input type="file" id="file_id">
<input type="button" value="上傳" id="btn1">
<script src="/static/js/jquery.js"></script>
<script>
$("#btn1").click(function () {
// 封裝數據
let formdata = new FormData();
formdata.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val());
// 將f_name 傳到後端當字典的鍵,另一個則是一個對象
formdata.append('f_name', $("#file_id")[0].files[0]);
// 處理ajax請求
$.ajax({
url: "",
type: "POST",
processData: false, // 告訴jQuery不要去處理髮送的數據
contentType: false, // 告訴jQuery不要去設置Content-Type請求頭
data: formdata,
// 成功後返回的數據
success: function (ret) {
console.log(ret)
}
})
})
</script>
</body>
獲取頁面的文件對象步驟:
def upload_ajax(request):
if request.method == "GET":
return render(request, "upload_ajax.html")
else:
print(request.POST)
# print(type(request.POST.get("fi_name1"))) #<class 'str'> 沒有意義
# print(request.body) # enctype="multipart/form-data" ,會報錯
print(request.FILES)
print(request.FILES.get('f_name'))
print(type(request.FILES.get('f_name')))
file_obj = request.FILES.get('f_name')
print(file_obj.name)
with open(os.path.join("media", file_obj.name), "wb") as f:
for i in file_obj:
f.write(i)
return HttpResponse("ok")
後端視圖代碼基本和基礎表單上傳文件的同樣。
ContentType指的是請求體的編碼類型,常見的類型共有3種:
這應該是最多見的 POST 提交數據的方式了。瀏覽器的原生 <form> 表單,若是不設置 enctype 屬性,那麼最終就會以 application/x-www-form-urlencoded 方式提交數據。請求相似於下面這樣(無關的請求頭在本文中都省略掉了):
POST http://www.example.com HTTP/1.1
Content-Type: application/x-www-form-urlencoded;charset=utf-8
user=hsz&age=22
這又是一個常見的 POST 數據提交的方式。咱們使用表單上傳文件時,必須讓 <form> 表單的 enctype 等於 multipart/form-data。直接來看一個請求示例:
POST http://www.example.com HTTP/1.1
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="user"
hsz
------WebKitFormBoundaryrGKCBY7qhFd3TrwA
Content-Disposition: form-data; name="file"; filename="chrome.png"
Content-Type: image/png
PNG ... content of chrome.png ...
------WebKitFormBoundaryrGKCBY7qhFd3TrwA--
這個例子稍微複雜點。首先生成了一個 boundary 用於分割不一樣的字段,爲了不與正文內容重複,boundary 很長很複雜。而後 Content-Type 裏指明瞭數據是以 multipart/form-data 來編碼,本次請求的 boundary 是什麼內容。消息主體裏按照字段個數又分爲多個結構相似的部分,每部分都是以 --boundary 開始,緊接着是內容描述信息,而後是回車,最後是字段具體內容(文本或二進制)。若是傳輸的是文件,還要包含文件名和文件類型信息。消息主體最後以 --boundary-- 標示結束。關於 multipart/form-data 的詳細定義,請前往 rfc1867 查看。
這種方式通常用來上傳文件,各大服務端語言對它也有着良好的支持。
上面提到的這兩種 POST 數據的方式,都是瀏覽器原生支持的,並且現階段標準中原生 <form> 表單也只支持這兩種方式(經過 <form> 元素的 enctype 屬性指定,默認爲 application/x-www-form-urlencoded。其實 enctype 還支持 text/plain,不過用得很是少)。
隨着愈來愈多的 Web 站點,尤爲是 WebApp,所有使用 Ajax 進行數據交互以後,咱們徹底能夠定義新的數據提交方式,給開發帶來更多便利。
application/json 這個 Content-Type 做爲響應頭你們確定不陌生。實際上,如今愈來愈多的人把它做爲請求頭,用來告訴服務端消息主體是序列化後的 JSON 字符串。因爲 JSON 規範的流行,除了低版本 IE 以外的各大瀏覽器都原生支持 JSON.stringify,服務端語言也都有處理 JSON 的函數,使用 JSON 不會趕上什麼麻煩。
JSON 格式支持比鍵值對複雜得多的結構化數據,這一點也頗有用。記得我幾年前作一個項目時,須要提交的數據層次很是深,我就是把數據 JSON 序列化以後來提交的。不過當時我是把 JSON 字符串做爲 val,仍然放在鍵值對裏,以 x-www-form-urlencoded 方式提交。