一、Ajax
'''页面不刷新的情况下可以与后端进行数据交互
异步提交 局部刷新
eg:码云用户注册 无序点击按钮内部也可以完成数据交互
ajax不是一门全新知识 本质就是一些js代码 我们学习ajax直接使用jQuery封装之后的版本(语法更简单) 使用ajax的前提必须要引入jQuery文件'''
# ajax和form的区别
ajax提交数据页面不用刷新 原始数据还在 处理数据的过程中不影响页面其他操作
form表单提交数据页面刷新 原始数据不在 并且处理数据的过程中无法做其他操作
1.代码实现
'''eg:页面上放三个input框 前面两个输入数字 第三个计算两个数字的和 按完按钮之后页面不能刷新 而且框中的数字不能消失'''
# form表单是实现不了的, form表单已提交就会直接刷新页面
$('#btn').click(function (){ # 给按钮绑定点击事件
# 获取两个框里面的数据
let i1Val = $('#i1').val();
let i2Val = $('#i2').val();
# 发送ajax请求传输数据
$.ajax({
url:'', # 不写默认就是当前页面所在的地址
type:'post', # 指定当前请求方式
data:{'i1':i1Val,'i2':i2Val}, # 请求携带的数据 后端通过K获取值
success:function (arg){ # 异步回调函数 后端有回复自动触发
$('#i3').val(arg)
}
})
})
# 这样就可以在页面实现不刷新 给后端提交数据
2.基础语法
$.ajax({
url:'', # 控制数据的提交地址 不写就是默认给当前地址提交
type:'', # 控制请求方式(默认get请求)
data:{}, # 组织提交的数据 后端按照K取值
success:function(形参){ # 形参就是接收后端返回的值
# 异步回调函数 可以根据后端返回的值操作
}
})
二、数据编码格式
# 当我们进行前后端文件传输的时候是依据数据的编码格式的
# form表单修改编码格式的属性为:enctype
# ajax修改编码格式的属性为:Content-Type
'''
请求体中携带编码方式
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
django针对不同编码方式对应的数据格式会采用不同的处理策略
'''
# form表单默认发送的编码格式:
Content-Type: application/x-www-form-urlencoded
数据格式:username=jason&password=123
django后端会自动处理到:request.POST
# form表单发送文件
Content-Type:multipart/form-data
数据格式:隐藏了不让看
django后端会自动处理:request.POST request.FILES
# ajax默认的编码格式
Content-Type: application/x-www-form-urlencoded
数据格式:username=jason&password=123
django后端会自动处理到:request.POST
'''ajax和form表单默认的编码格式都是urlencoded
form表单发送文件需要把编码格式修改为 multipart/form-data
form表单不能传输json格式数据 需要使用ajax
'''
三、ajax携带文件数据
# form表单发送文件数据就只需要把编码格式修改为 multipart/form-data 那ajax怎么携带文件数据呢?
# 前端
$('#d3').click(function () {
# 产生一个对象
let formData = new FormData()
# 添加普通数据
formData.append('username',$('#d2').val())
# 添加文件数据
formData.append('file',$('#d1')[0].files[0]) # 后端就是根据前面字符串提取数据 第一个索引变成标签对象 如果是多个文件第二个索引可以不用加
$.ajax({
url:'',
type:'post',
data:formData,
# 添加文件数据需要写两个固定参数
contentType:false, # 不用任何编码
processData: false, # 不处理数据对象
success:function (args){
}
})
})
# 后端
username = request.POST.get('username')
file = request.FILES.get('file')
# 后端还是一样的
四、ajax发送json格式数据
# 前后端交互数据一般都是使用json格式数据 form表单是发送不了json格式数据的 只能使用ajax
# 前端:
$('#d1').click(function (){
$.ajax({
url: '',
type: 'post', # 不写默认是get请求
contentType:'application/json', # 不写默认是urlencoded编码
data: JSON.stringify({'name': 'jason', 'pwd': 123}), # 直接发送json格式数据
success: function (args) {
}
})
})
# 后端:
'''django后端针对json格式的数据不会做任何的处理 就在request.body内
需要我们自行处理'''
print(request.POST, request.FILES) # <QueryDict: {}> <MultiValueDict: {}>
# 所以POST和FILES是拿不到前端发送过来的json格式数据的
# 需要在request.body中获取
print(request.body) # b'{"name":"jason","pwd":123}' 是bytes类型
data_json = request.body
data = json.loads(data_json) # json自带解码功能
print(data, type(data)) # {'name': 'jason', 'pwd': 123} <class 'dict'>
五、回调函数
# 后端跟ajax交互 不应该再返回一个页面 而是返回一个json格式数据
# 向我们之前学习的三板斧render、redirect、HttpResponse
前两者都是返回一个页面 这样就算返回了前端也不会跳转
HttpResponse返回一个字符串其实也会被回调函数的参数接收
# 现在我们在后端发送给前端json格式数据
# 后端
return HttpResponse(json.dumps({'name': 'jason', 'pwd': 123}))
# 前端
console.log(args) # {"name": "jason", "pwd": 123}
console.log(typeof args) # string
# 我们发现后端发送过来的json格式数据是不会帮我们反序列化的
success: function (args) {
let Data = JSON.parse(args) # 需要我们手动反序列化
console.log(typeof Data) # object
console.log(Data) # {name: 'jason', pwd: 123}
console.log(Data.name) # jason
}
# 但是这是使用HttpResponse返回的 现在我们使用JsonResponse返回看看
# 后端
return JsonResponse({'name': 'jason', 'pwd': 123})
# 前端
success: function (args) {
console.log(typeof args) # object
console.log(args) # {name: 'jason', pwd: 123}
console.log(args.name) # jason
}
'''
使用JsonResponse返回数据前端是会自动帮我们反序列化的
因为HttpResponse返回的其实就是一个字符串对象 前端所以不会反序列化
而JsonResponse返回的是一个json格式数据 前端就会帮我们自动反序列化
而如果想让HttpResponse自动反序列化需要加一个参数 dataType:'JSON'
dataType:'JSON',
success: function (args) {
console.log(typeof args) // object
console.log(args) // {name: 'jason', pwd: 123}
console.log(args.name) // jason
}
'''
六、序列化
# 当我们以后前后端分离会后 前端是不识别 django ORM产生的Queryset数据对象的 所以还是需要json格式数据
# 后端:
data_list = [] # 数据格式为 [{}, {}, {}]
user_queryset = models.Book.objects.filter()
for obj in user_queryset:
data_dict = {}
data_dict['pk'] = obj.pk
data_dict['title'] = obj.title
data_dict['publish'] = obj.publish.name
data_list.append(data_dict)
return HttpResponse(json.dumps(data_list))
# 这样有点代码冗余 django自带了序列化组件
# 后端:
from django.core import serializers
user_list = models.Book.objects.filter()
res = serializers.serialize('json', user_list) # 第一个参数决定以什么方式序列化数据
return HttpResponse(res)
# 可以去bejson官网看下我们发送给前端的json格式的数据张啥样 这就是以后如果前后端分离 我们需要发送给前端的json格式数据
七、作业
# 使用sweetalert做删除二次确认
后端:
def delete(request):
if request.method == 'POST':
data_id = request.POST.get('delete_id')
models.Book.objects.filter(pk=data_id).delete()
return HttpResponse('删除成功')
# 前端
<a href="#" class="btn btn-danger btn-xs subBtn" delete_id = {{ book_obj.id }}>删除</a>
$('.subBtn').click(function (){
let dataEle = $(this).attr('delete_id') # 获取删除的书籍id
swal({
title: "你确定要删除把",
text: "你在想想吧",
icon: "warning",
buttons: ['取消', '确定'],
dangerMode: true,
})
.then((willDelete) => {
if (willDelete) {
$.ajax({
url:'/delete/', # 朝删除网址发送
type:'post',
data:{'delete_id':dataEle},
success:function (args){
swal(args, {icon: "success",})
}
})
} else {
swal("不删就好");
}
});
})