Ajax准備知識
Ajax介紹
AJAX(Asynchronous Javascript And XML)翻譯成中文就是“異步的Javascript和XML”。即使用Javascript語言與服務器進行異步交互,傳輸的數據為XML(當然,傳輸的數據不只是XML)。
Ajax並不是一門新的語言 它其實就是基於JS寫的一個功能模塊而已。
AJAX 最大的優點是在不重新加載整個頁面的情況下,可以與服務器交換數據並更新部分網頁內容。(這一特點給用戶的感受是在不知不覺中完成請求和響應過程)。
AJAX 不需要任何瀏覽器插件,但需要用戶允許JavaScript在瀏覽器上執行。
- 同步交互:客戶端發出一個請求后,需要等待服務器響應結束后,才能發出第二個請求;
- 異步交互:客戶端發出一個請求后,無需等待服務器響應結束,就可以發出第二個請求。
AJAX 1、AJAX是什么 前端向后端發送請求的方式 2、前端向后端發送請求的方式 1、直接在瀏覽器地址欄輸入URL訪問 -->GET 2、點擊a標簽跳轉到指定頁面 -->GET 3、form表單 -->GET/POST 4、AJAX -->GET/POST
AJAX的兩個關鍵點:局部刷新,異步請求
JQuery實現Ajax
案例:
頁面上有三個input框 一個按鈕
用戶在前兩個框中輸入數字 點擊按鈕保證頁面不刷新的情況下將數據發到后端做計算,然后將計算好的結果再發給前端展示到第三個input框中
<script> $('#d1').click(function () { //獲取兩個框里面的內容,朝后端提交異步請求 //ajax基本語法 $.ajax({ // 1.指定朝哪個后端提交數據 url:'',//控制數據的提交路徑 有三種寫法 跟form表單的action屬性一致 // 2.指定當前請求方式 type:'post', // 3.指定提交的數據 data:{'i1':$('#i1').val(),'i2':$('#i2').val()}, // 4.ajax是異步提交,所以需要給一個回調函數來處理返回結果 success:function (data) { // data就是異步提交的返回結果 //將異步提交的結果通過DOM操作渲染到第三個input框里 {$('#i3').val(data)} } })
注意,Ajax提交數據需要把中間件注釋掉

def index(request):
if request.method =='POST':
i1 = request.POST.get('i1')
i2 = request.POST.get('i2')
# i1,i2是字符串類型,需要先做類型轉換
i3 = int(i1) + int(i2)
return HttpResponse(i3)
return render(request,'index.html')
Views.py
頁面展示:
content-type 編碼格式
form表單
點開瀏覽器檢查Network 發現form表單傳輸的數據默認是urlencoded
urlencoded數據格式:
username=jason&password=123
django后端針對該格式的數據 會自動解析並幫你打包到request.POST中
如果提交的是文件
后端獲取的只是文件名
formdata數據格式
后端獲取的是文件對象
django后端針對符合urlencoded編碼格式數據(普通鍵值對)還是統一解析到request.POST中
而針對formdata文件數據就會自動解析放到request.FILES中
Ajax
Ajax默認的也是urlencoded編碼格式
但Ajax還可以發json格式的數據
注意:前后端數據交互 編碼格式與數據格式一定要一致,不能騙人家!!!
//發json格式 $('#d2').on('click',function () { $.ajax({ url:'', type:'post', // 修改content-Type參數 contentType:'application/json', //把默認的urlencoded編碼格式改成json數據的格式 data:JSON.stringify({'username':'jason','password':123}), // 將數據序列化成json格式字符串 success:function (data) { alert(data) } })
由瀏覽器檢查可知,此時發的就是json數據了
django后端針對json格式數據 並不會做任何的處理,而是直接放在request.body中,需要自己處理二進制的json格式
import json #自己處理json格式數據 json_bytes = request.body #先解碼 # json_str = json_bytes.decode('utf-8') #再反序列化 # json_dict = json.loads(json_str) #擴展 json.loads能夠自動解碼並序列化 json_dict = json.loads(json_bytes) print(json_dict,type(json_dict))
Ajax發送文件:
Ajax有一個內置對象FormData,既發可以普通鍵值對也可以發文件
// ajax發送文件數據 需要借助於內置對象 $('#d3').click(function () { // 1 需要先生成一個內置對象 var myFormData = new FormData(); // 2 傳普通鍵值對 當普通鍵值對較多的時候 我們可以利用for循環來添加 myFormData.append('username','jason'); myFormData.append('password',123); // 3 傳文件 myFormData.append('myfile',$('#i1')[0].files[0]); // 獲取input框內部用戶上傳的文件對象 // 發送ajax請求 $.ajax({ url:'', type:'post', data:myFormData, // 發送formdata對象需要指定兩個關鍵性的參數 processData:false, // 讓瀏覽器不要對你的數據進行任何的操作 contentType:false, // 不要使用任何編碼格式 對象formdata自帶編碼格式並且django能夠識別該對象 success:function (data) { alert(data) } }) })
由下圖可知,此時就可以拿到文件對象和普通鍵值對了
序列化
Django內置的serializers
前后端交互一般都是一個大字典,后端會給前端寫一個接口文檔,表明大字典內都有哪些鍵值對,然后前端根據字典就可以取到想要的值。
那么這個時候,就可以用Django給我們提供的序列化方式 serializers
#導入內置序列化模塊 from django.core import serializers def ab_se(request): #拿到用戶表里面的所有的用戶對象 user_queryset = models.Userinfo.objects.all() #調用該模塊下的方法,第一個參數是你想以什么樣的方式序列化你的數據 res = serializers.serialize('json',user_queryset) # return render(request,'ab_se.html',locals()) ''' or ''' return HttpResponse(res)
補充:上傳文件和json序列化
Ajax XHR就是看ajax請求 content_type是前后端數據交互的一種格式text、html、applicaiton/json等等 ``` 特性: 1.異步請求 2.局部刷新 $.ajax({ url:'/login/', type:'post', data:{ username:$('[name=username]').val(), password:$('[name=password]').val(), csrfmiddlewaretoken:$('[name=csrfmiddlewaretoken]').val(), }, success:function(response){ var response = JSON.parse(response); #反序列化 response 視圖函數返回值 } }) ``` # 今日內容 ## 上傳文件 ## form表單上傳文件 urlencoded 格式 name=xx&ss=ss... ``` <form action="/upload/" method="post" enctype="multipart/form-data"> # 重點 {% csrf_token %} 頭像: <input type="file" name="head-pic"> 用戶名: <input type="text" name="username"> <input type="submit"> </form> def upload(request): if request.method == 'GET': return render(request,'upload.html') else: print(request.POST) #拿到的是post請求的數據,但是文件相關數據需要用request.FILES去拿 print(request.FILES) #<MultiValueDict: {'head-pic': [<InMemoryUploadedFile: 1.png (image/png)>]}> file_obj = request.FILES.get('head-pic') print(file_obj) file_name = file_obj.name # f = open('xx.txt','rb') # with open('xx.txt','wb') as f2: # for i in f: # f2.write(i) import os path = os.path.join(settings.BASE_DIR,'statics','img',file_name) with open(path,'wb') as f: for i in file_obj: f.write(i) #for chunk in file_obj.chunks(): # f.write(chunk) return HttpResponse('ok') ``` ## ajax上傳文件 ``` var formdata = new FormData(); formdata.append('user',$('#username').val()) formdata.append('csrfmiddlewaretoken',$('#csrfmiddlewaretoken').val()) formdata.append('file',$('#file')[0].files[0]) $.ajax({ url:'/upload/', type:'post', data:formdata, success:function(response){ response } }) def upload(request): if request.method == 'GET': return render(request,'upload.html') else: print(request.POST) #拿到的是post請求的數據,但是文件相關數據需要用request.FILES去拿 print(request.FILES) #<MultiValueDict: {'head-pic': [<InMemoryUploadedFile: 1.png (image/png)>]}> file_obj = request.FILES.get('head-pic') print(file_obj) file_name = file_obj.name # f = open('xx.txt','rb') # with open('xx.txt','wb') as f2: # for i in f: # f2.write(i) import os path = os.path.join(settings.BASE_DIR,'statics','img',file_name) with open(path,'wb') as f: for i in file_obj: f.write(i) #for chunk in file_obj.chunks(): # f.write(chunk) return HttpResponse('ok') ``` ## JsonResponse ``` def index(request): d1 = {'name':'chao'} import json return HttpResponse(json.dumps(d1)) -- success:function(res){ var a = JSON.parse(res) } return HttpResponse(json.dumps(d1),content-type='application/json') --success:function(res){res--自定義對象,不需要自己在反序列化了} return JsonResponse(d1) d1 = [11,22] #非字典類型的數據都需要加safe=False return JsonResponse(d1,safe=False) ``` 獲取多對多數據的時候 ``` authors = request.POST.getlist('authors') ``` ## json序列化時間日期類型的數據的方法 ``` import json from datetime import datetime from datetime import date #對含有日期格式數據的json數據進行轉換 class JsonCustomEncoder(json.JSONEncoder): def default(self, field): if isinstance(field,datetime): return field.strftime('%Y-%m-%d %H:%M:%S') elif isinstance(field,date): return field.strftime('%Y-%m-%d') else: return json.JSONEncoder.default(self,field) d1 = datetime.now() dd = json.dumps(d1,cls=JsonCustomEncoder) print(dd) ``` from django.conf import settings 全局的設置,區別於用戶的設置 form表單input標簽需要寫name屬性 ajaxinput標簽不需要寫name屬性,因為與data里的鍵名有關 $ajax({ url:'/upload/', tyepe:'post', data:{aa:&('#name').val(), #django里request.POST.get(''aa') #與input里提交數據不一樣 }) date,datetime類型轉json 見xx.py