前后端傳輸數據的編碼格式(contentType)
get請求數據就是直接放在url?后面的
url?usernmae=junjie&password=123...
可以向后端發送post請求的方式
- form請求
- ajax請求
前后端傳輸數據的編碼格式
- urlencoded
- formdata
- json
研究form表單:默認的數據編碼格式是(urlencoded)
結論:Django針對urlencoded編碼格式的數據會自動幫你解析封裝到request.POST中。
那么文件是什么數據類型?
結論:如果將編碼格式改為form-data,那么針對普通的鍵值對還是解析到request.POST,但是針對文件類型格式解析到request.FILES中。
Django進行了二次封裝,后端針對不同的編碼格式在后端內部做不同的編碼解析,並放到不同的方法中。
form表單只能發送urlencoded以及formdata兩種編碼格式。
那么Ajax是什么數據格式?
結論:默認也是urlencoded,數據格式username=junjie&age=20。所有后端需要request.POST接受數據
ajax發送JSON格式數據
前后端傳輸數據的時候一定要確保編碼格式與數據真正的格式是一致的。
JSON.stringify 前端將數據轉為JSON格式 與 contentType:'application/json' 指定字符編碼格式
<script>
$('#d1').click(function(){ // button按鈕觸發點擊事件
$.ajax({
url:'',
type:'post',
data:JSON.stringify({'username':'junjie','age':18}),//數據也需要轉為JSON格式。
contentType:'application/json',//指定字符編碼格式
success:function (){
}
})
})
</script>
在前后端傳輸數據的編碼格式(contentType)中推導request.POST只能接收username=junjie&age=18
這類的格式,那么是否可以推導前端返回JSON在reuqest.POST
中肯定無法找到。
代碼驗證:
def ab_ajax(request):
print(request.POST)
return render(request,'ab_ajax.html')
補充:如何判斷當前請求是否為ajax請求?
request.is_ajax() # 判斷當前請求是否是ajax請求,返回布爾值。
現在想想前后端數據交互,基於網絡傳輸時,是什么格式?
二級制格式。
def ab_ajax(request):
if request.is_ajax():
# print(request.is_ajax())
print(request.body) # b'{"username":"junjie","age":18}'
return render(request, 'ab_ajax.html')
后端拿到二進制格式的JSON格式字符串。Django針對json格式數據后端需要手動處理。
后端如何處理json格式字符串
import json
def ab_ajax(request):
if request.is_ajax():
# print(request.is_ajax())
# print(request.body)
# json_bytes = request.body # 獲取到前端發送過來的二進制json格式數據
# json_str = json_bytes.decode('utf8') # 解碼,utf8格式
# json_loads = json.loads(json_str) # 反序列化至數據初始格式
# print(json_loads) # {'username': 'junjie', 'age': 18}
json_bytes = request.body
json_dict = json.loads(json_bytes)
print(json_dict) # {'username': 'junjie', 'age': 18}
# json.loads括號內如果傳入一個二進制數據,內部會自動解碼再返序列化
return render(request, 'ab_ajax.html')
總結,ajax發送json格式數據需要注意的點:
- contentType 參數 指定成 : application/json
- 數據必須是真正的json格式數據
- Django后端不會處理json格式數據,需要到request.body獲取並處理
Ajax發送文件
ajax發送文件需要借助於js內置對象FormData
<script>
//點擊按鈕向后端發送普通鍵值對和文件數據
$('#d4').click(function (){
//1.利用FormData內置對象
let obj = new FormData();
//2.添加普通的鍵值對
obj.append('username',$('#d1').val()); //val()// 取得第一個匹配元素的當前值 等同於value()
obj.append('password',$('#d2').val());
//3.添加文件對象,$('#d3')取索引0,轉為原生jQuery對象即原生標簽對象,再用files[0]就獲得用戶傳的文件對象
obj.append('myfile',$('#d3')[0].files[0])
//4.將對象基於ajax發送到后端
$.ajax({
url:'',
type:'post',
data:obj, //直接將對象放在data中即可
// ajax 發送文件必須指定兩個參數
contentType:false, //告訴瀏覽器不需要帶任何編碼,Django后端能夠自動識別formdata對象,
processData: false, //告訴瀏覽器,不要對數據進行任何處理,原封不動發送到后端。
success:function (args){}
})
})
</script>
def myfile(request):
if request.is_ajax():
if request.method == 'POST':
print(request.POST)
# <QueryDict: {'username': ['junjie'], 'password': ['123']}>
print(request.FILES)
# <MultiValueDict: {'myfile': [<InMemoryUploadedFile: 截屏2022-03-02 22.19.54.png (image/png)>]}>
return render(request, 'myfile.html')
django后端會自動識別formdata對象,將前端返回的數據防止對應的請求中。
總結,ajax發送文件需要注意的點:
-
需要利用內置對象FormData,普通鍵值對和文件都能發送
obj.append('username',$('#d1').val()); obj.append('password',$('#d2').val()); obj.append('myfile',$('#d3')[0].files[0])
-
需要指定兩個關鍵性的參數
contentType: false processData: false
-
Django后端能夠直接識別formdata對象,並且能夠將內部的普通鍵值對自動解析並封裝到你request.POST中,文件數據對象自動解析並封裝到reuqest.FILES中
Django自帶的序列化組件(drf做鋪墊)
借助於模板語法前端顯示數據對象。
但是,由此前端能夠顯示用戶對象是借助了模板語法,如果現在做一個前后端交互,前端不是Django框架, 前后端分離,那么此時無法借助於模板語法,就需要手擼前后端交互,前后端交互就要使用到JSON格式。
將后端數據結構構造為列表套字典[{},{},{}...]
,為什么要構造成列表套字典呢?
首先數據有多個,列表套字典在后端有對應的數據,在JSON,JS中也有對應的數據,恰好可以實現前后端交互,JSON可以序列化列表格式,字典格式也可以,前端JS反序列化后可以得到數組套一個個的自定義對象,再通過for循環可以拿到一個個的自定義對象,再通過.
點的方式就可以取值。
后端邏輯代碼:
def gender(request):
user_queryset = models.User.objects.all()
user_list = []
for i in user_queryset:
tmp = {
'pk':i.pk,
'username':i.username,
'age':i.age,
'gender':i.get_gender_display() # models.py中性別使用了choice參數,取值方式改變了。
}
user_list.append(tmp)
return JsonResponse(user_list,safe=False)
此時返回給前端的數據格式為列表套字典,字典中有一個個鍵值對 。
做前后端分離項目,后端要將數據代碼處理並序列化到前端。
上述代碼為手動更改數據類型為JSON,但是如果數據成百上千也要手動嗎?
模塊:from django.core import serializers,自動將數據編程json格式字符串。
from django.core import serializers
def gender(request):
user_queryset = models.User.objects.all()
res = serializers.serialize('json', user_queryset)
return HttpResponse(res)
后端寫接口就是利用序列化組價渲染數據並寫一個接口文檔,比如,告訴前端,gender中的數字代表什么。