day67——前后端传输数据的编码格式、ajax传json数据/传文件、批量插入
前后端传输数据的编码方式(contentType)
get请求数据会在url后面用?拼接,我们不做研究,主要研究post请求的编码格式。
可以朝后端发请求的方式:
-
浏览器地址栏输入url回车(GET/POST请求)
-
a便签的href属性(GET)
-
form表单(GET/POST请求)
默认是GET请求
method='get'
修改
method='post'
朝后端发送的是post请求 -
ajax(GET/POST请求)
默认是GET请求
type='get'
修改
type='post'
发送post请求
前后端传输数据的三种编码格式:
- urlencoded
- formdata
- json
form表单传输数据的编码方式:
默认编码格式:urlencoded
数据格式:username=tom&password=111,跟get请求url问号后携带数据的格式相同
AJAX传输数据的编码方式:
默认编码格式:urlencoded
数据格式:username=tom&password=111
结论:django后端会将urlencoded编码格式的数据都封装解析到request.POST中,如果手动的将form表单的编码格式换成formdata,那么普通的数据还是封装进request.POST内,不同的是针对文件类型的数据会被解析封装到request.FILES中;form表单无法发送json格式数据。
AJAX发送json格式数据
不同程序/应用之间进行数据交互的时候 一定要确保数据格式和编码一致;以json为传输的编码格式(contentType:'application/json')那么数据就必须是json格式的数据。
前端页面:
<body>
<button class="btn btn-success btn-md">提交
</button>
<script>
$('.btn').click(function () {
$.ajax({
url:'',
data:JSON.stringify({'username':'jason','age':25}), //将字段序列化成json格式的字符串
type:'post',
contentType:'application/json', // 修改编码格式为json格式
dataType:'json',
success:function () {
}
})
})
</script>
</body>
后端:
django在针对json格式编码的数据,不会做任何的处理,不会将其封装到request.POST或者request.FILES中,而在存在于request.body中,需要我们自己获取并进行处理(反序列化)。
# 序列化方式一
import json
json_bytes = request.body
json_str = json_bytes.decode('utf-8')
json_str = json.loads(json_bytes)
# loads补充:
"""
json.loads括号内如果传入的是一个二进制格式的数据,
那么内部会自动先解码再反序列化"""
# 方式二 简写
json_str = json.loads(json_bytes) # 括号内直接放二进制的数据。
ajax发送文件
前端
ajax在发送文件时需要借助与js内置对象FormDate获取一个formDate对象,然后往对象内append属性,添加属性的时既可以添加普通的键值对也可以添加文件对象,ajax数据部分直接放formDate对象即可。
发送文件必须指定的两个参数:
contentType:false
:告诉django不要使用任何的编码方式编码,django后端会自动识别formDate对象process:false
:告诉浏览器不要对数据进行任何的处理。
<body>
<input type="text" class=" form-control" id="d1">
<input type="file" class=" form-control" id="d2">
<button class="btn btn-success" id="d3">点我</button>
<script>
$('#d3').on('click',function () {
// 1 需要先利用FormData内置对象获取一个FormDate对象,
let formDate_obj = new FormData();
// 2 添加普通的键值对
formDate_obj.append('username',$('#d1').val());
// 3 添加文件对象
formDate_obj.append('myfile',$('#d2')[0].files[0]);
// $('#d2')查询到是jQuery对象,取索引[0]转为标签对象,
// 标签对象才有获取文件对象的方法files,点files获取文件对象, // 取索引[0]获取到真正的文件。
// 4 将对象基于ajax发送给后端
$.ajax({
url:'',
type:'post',
data:formDate_obj,
contentType:false,
processData:false,
success:function (args) {
}
})
})
</script>
</body>
后端
在request.POST获取文件数据并进行处理。
def ab_file(request):
if request.is_ajax():
if request.method == 'POST':
print(request.POST)
print(request.FILES)
return render(request,'ab_file.html')
django后端能够直接识别到formdata对象并且能够将内部的普通键值自动解析并封装到request.POST中,文件数据自动解析并封装到request.FILES中
django自带的序列化组件(为drf做铺垫)
前后端分离:
在写前后端分离的项目时,前端页面无法使用模版语法获取数据,需要在后端将数据序列化好之后再传给前端,前端才能识别。
一般作为后端开发的程序员只需要写代码将数据处理好,能够序列化返回给前端,之后再写一个接口文档 告诉前端每个字段代表的意思即可。
需求:在前端获取到后端用户表里面所有的数据,并且要是列表套字典的形式。
纯手动序列化数据:
def seria_json(request):
import json
user_queryset = models.User.objects.all()
list_1 = []
for user_obj in user_queryset:
tem_dict ={
'name':user_obj.name,
'age':user_obj.age,
'gender':user_obj.get_gender_display()
}
list_1.append(tem_dict)
list_1 = json.dumps(list_1)
return HttpResponse(list_1)
这样的方式过于繁琐,并且字段过多时一个个添加键值对不现实。
借助与django序列化组件serializers
from django.core import serializers
res = serializers.serialize('json',user_queryset)
"""
第一个参数是序列化的格式,第二个参数直接放包含表中所有数据的queryset对象即可,
会自动帮你将数据变成json格式的字符串,并且内部非常的全面"""
return HttpResponse(res)
还可以用一些网址对json格式的数据进行解析格式化数据。
格式化之后的数据
"""
[{
"model": "app01.user",
"pk": 1,
"fields": {
"name": "jaosn",
"age": 18,
"gender": 1
}
}, {
"model": "app01.user",
"pk": 2,
"fields": {
"name": "tank",
"age": 19,
"gender": 2
}
}]"""
写接口就是利用序列化组件渲染数据然后写一个接口文档,该交代交代一下就可以了。
AJAX结合sweetalert
AJAX结合sweetalert实现删除的二次确认
<script>
$('.del').on('click',function () {
let deleteElement =$(this)
swal({
title: "你确定要删吗",
text: "删了数据就没有了哦!",
type: "warning",
showCancelButton: true,
confirmButtonClass: "btn-danger",
confirmButtonText: "是的!",
cancelButtonText: "算了!",
closeOnConfirm: false,
closeOnCancel: false,
showLoaderOnConfirm: true
},
function(isConfirm) {
if (isConfirm) {
$.ajax({
// 1. 删除数据的主键值拼接在url后面
// url:'/user_delete/'+deleteElement.attr('delete_id'),
url:'/user_delete/',
// 2. 删除数据的主键值放在请求体里面
data:{'delete_id':deleteElement.attr('delete_id')},
type:'post',
success:function(args){
// 判断响应状态码 然后做不同的处理
if(args.code===1000){
swal('删了', args.msg, "success")
// 1.直接刷新当前页面
{#window.location.reload()#}
// 2.利用DOM操作 动态刷新
deleteElement.parent().parent().remove()
}
else{
swal('完了', '出现了未知的错误', "info")
}
}
})
} else {
swal("算了算了", "工作要紧", "error");
}
});
})
</script>
后端:
def user_delete(request):
from django.http import JsonResponse
import time
if request.is_ajax():
time.sleep(3)
delete_id = request.POST.get('delete_id')
back_dict = {'code': 1000, 'msg': ''} # code响应状态码用于前端判断是否删除成功
models.User.objects.filter(pk=delete_id).delete()
back_dict['msg'] = '数据已经删除'
return JsonResponse(back_dict)
批量插入
当插入的数据量很大时一条条插入数据耗时较长,选择批量插入操作时间会大大降低,提升效率。。
def batch_create(request):
# 第一种:一条条插入
# for i in range(1000):
# models.Book.objects.create(title=f'第{i}书')
# book_queryset = models.Book.objects.all()
# 第二种:使用bulk_create批量插入
obj_list = []
for i in range(10000):
book_obj = models.Book(title=f'第{i}本书')
obj_list.append(book_obj)
models.Book.objects.bulk_create(obj_list)
book_queryset = models.Book.objects.all()
return render(request, 'batch_create.html', locals())