前后端传输数据的编码格式(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中的数字代表什么。