django之ajax-sweetalert-contentType
Ajax
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。
使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点:不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。这一特点给用户的感受是在不知不觉中完成请求和响应过程。
AJAX 的特点:异步提交、局部刷新
原生JS实现的Ajax过于复杂,实际项目中一般不用。
我们现在学习jQuery封装版本的Ajax,所以需要前端页面实现导入了jQuery模块。
其实并不时只有jQuery能够实现Ajax,其他框架或者模块也可以,原理都是一样的。
Ajax基本操作
通过一个小案例来介绍Ajax的基本使用
# 需求:
1.前端页面有2个输入框,1个输出框
2.在两个输入框中输入数字,点击按钮,第三个输出框显示两个数字之和。
前端页面,ajax提交post请求
<input type="text" id="d1"> +
<input type="text" id="d2"> =
<input type="text" id="d3">
<p><button id="cal-btn">计算</button></p>
<script>
$('#cal-btn').click(function () {
$.ajax({
url:'',
type:'post',
data: {'d1': $('#d1').val(), 'd2': $('#d2').val()},
success:function (args) {
$('#d3').val(args)
}
})
})
</script>
参数:
- url: 提供ajax请求的路由,可以有三种方式:全称/后缀/不写(默认当前页面的url)
- type: 指定ajax请求的方式,get/post, 默认是get请求
- data: 请求提供的数据,键值对的方式存放在自定义对象中
- success: 回调函数,当请求收到响应后自动触发执行。args是接收响应数据的形参。
- dataType: 扩展参数,dataType:'JSON', 表示希望接收json格式的数据
补充:当后端以HttpResponse返回的json格式的数据,默认是不会自动反序列化
- 1.手动序列化:JSON.stringify()
- 2.配置参数:dataType 结论:写ajax的时候直接将dataType参数加上,以防万一,或者后端就用JsonResonse
后端逻辑
from django.shortcuts import render, HttpResponse
def ajax_text(request):
if request.method == 'GET':
return render(request, 'ajax_text.html')
d1 = request.POST.get('d1')
d2 = request.POST.get('d2')
d3 = int(d1) + int(d2)
return HttpResponse(d3)
# ajax提交的post请求携带的普通数据依然通过request.POST获取。
ajax发送json格式数据
ajax向后端发送json数据需要注意两点:
- 发送的数据必须是json格式的
- 必须设置:
contentType: 'application/json'
前端页面,ajax发送json数据
<script>
$('#cal-btn').click(function () {
$.ajax({
url: '',
type: 'post',
data: JSON.stringify({'d1': $('#d1').val(), 'd2': $('#d2').val()}),
contentType: 'application/json', // 必须 指定编码格式
success:function (args) {
alert(typeof args);
$('#d3').val(args)
}
})
})
</script>
ajax通过post请求提交的json格式数据,django不会再帮忙封装到request.POST
中,需要手动到request.body
中反序列化获取。
def ajax_json(request):
if request.is_ajax():
if request.method == 'POST':
request_dict = json.loads(request.body)
d1 = request_dict.get('d1')
d2 = request_dict.get('d2')
d3 = int(d1) + int(d2)
return HttpResponse(d3)
if request.method == 'GET':
return render(request, 'ajax_json.html')
补充总结:
request.is_ajax()
可以用来判断请求是否为ajax请求,返回布尔值。- 接收ajax的post方式提交的json数据将会原封不动的保存在
request.body
中,并且是二进制格式数据。从中获取数据需要分两步操作:解码、反序列化。使用的工具是json模块提供的loads()
方法。
# 方式1:分两步
request_str = request.body.decode('utf-8') # 解码
request_dict = json.loads(request_str) # 反序列化
# 方式2:一步到位
request_dict = json.loads(request.body) # 利用loads()的自动解码功能
ajax发送文件
ajax发送文件需要借助于js内置对象FormData
将文件数据和其他普通键值对数据封装到FormData
对象中
并且,还需要使用两个参数:contentType
、processData
<script>
$('#btn-submit').click(function () {
let formDataObj = new FormData(); // 将普通数据和文件添加到该对象中
formDataObj.append('username', $('#username').val());
formDataObj.append('avatar', $('#avatar')[0].files[0]);
$.ajax({
url: '',
type: 'post',
data: formDataObj,
contentType: false, // 必须的
processData: false, // 必须的
success: function (args) {
alert(args)
}
})
})
</script>
参数设置:
- contentType: false 告诉浏览器不要任何编码,django后端能够自动识别formdata对象
- processData: false 告诉浏览器不要对数据做任何处理
补充:
- jquery获取文件方式:$('#avatar')[0].files[0], jquert对象转js对象再取文件对象
- django后端能够直接识别formdata对象,并且能够将内部的普通键值自动解析并封装到request.POST中;文件数据自动解析并封装到request.FILES中
编码格式contentType
get请求携带的数据是直接放在url后面的,如
book_list/?page_id=1&delete_book_id=2
目前朝后端提交post请求的方式有2种
form表单 # 参数:method='post'
ajax请求 # 参数:type='post'
# 两者默认的提交方式都是get请求
前后端传输数据的编码格式:
urlencoded # 默认是 urlencoded
formdata # 传文件必须使用formdata
json
form表单提交post请求的编码格式
form表单默认使用的编码格式是urlencoded
,可以通过参数enctype
修改编码格式
# post提交数据采用的编码格式为:urlencoded
此时数据的格式为:username=the3times&password=123
django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中
# post提交数据采用的编码格式为:formdata
此时django将普通的键值对数据依然封装到request.POST中, 文件数据封装到request.FILES中
# post表单请求无法发送json格式数据
Ajax提交post请求的编码格式
ajax默认使用的编码格式也是urlencoded
,可以通过参数contentType
修改编码格式
# ajax提交数据采用的编码格式为:urlencoded
此时数据的格式为:username=the3times&password=123
django后端针对符合urlencoded编码格式的数据都会自动帮你解析封装到request.POST中
# ajax提交数据采用的编码格式为:formdata
# 借助js的FormData对象,将普通数据和文件数据都可以封装到该对象中再传给后端
此时django将普通的键值对数据依然封装到request.POST中, 文件数据封装到request.FILES中
let formDataObj = new FormData();
formDataObj.append('username', $('#username').val());
formDataObj.append('avatar', $('#avatar')[0].files[0]);
$.ajax({
url: '',
type: 'post',
data: formDataObj,
contentType: false, // 不需使用任何编码 django后端能够自动识别formdata对象
processData: false,
success: function (args) {
alert(args)
}
})
# ajax提交数据采用的编码格式为:json
此时数据原封不动的存放在request.body中,需要将二进制数据解码后再反序列化,获取其中的数据
$.ajax({
url: '',
type: 'get',
data: JSON.stringify({'d1': $('#d1').val(), 'd2': $('#d2').val()}),
contentType: 'application/json', // 指定编码格式
success:function (args) {
alert(typeof args);
$('#d3').val(args)
}
})
ajax结合sweetalert插件
ajax结合sweetaler插件实现删除数据的二次确认操作。
下载插件
- 将压缩包解压,直接将里面的
dist
文件夹拷贝粘贴到项目的静态数据文件夹中,通过link
标签和script
标签将其中的css文件和js文件加载到需要的html页面上。
使用插件
- 选择该网站中需要的弹出框形式,复制js代码,并修改。
案例介绍
ajax结合sweetalert实现图书管理页面书籍的删除二次确认操作。想看完整项目你就点一下
前端页面
{% for book_obj in book_queryset %}
<tr>
<td class="text-center">
<button class="btn btn-xs btn-danger btn-delete" delete_id="{{ book_obj.pk }}">删除</button>
</td>
</tr>
{% endfor %}
<script>
$('.btn-delete').click(function () {
let currentBtn = $(this); // 必须放着这个位置(当前点击的this),不要放在 if(isConfirm)里面了
swal({
title: "确定删除?",
text: "删除后将就找不回来了!",
type: "warning",
showCancelButton: true,
confirmButtonClass: "btn-danger",
confirmButtonText: "确定,删了它",
cancelButtonText: "算不吧,不删了!",
closeOnConfirm: false,
closeOnCancel: false,
// showLoaderOnConfirm: true, 增加该参数可以实现网络IO的等待效果
},
function(isConfirm) {
if (isConfirm) {
$.ajax({
url: '{% url "book_delete" %}',
type: 'post',
data: {'delete_id': currentBtn.attr('delete_id')},
success: function (args) {
if (args.status_code === 1111){
currentBtn.parent().parent().remove();
swal("删除成功!", args.msg, "success");
}else {
swal("删除失败!", args.msg, "success");
}
}
});
}else {
swal("取消操作", "没有删除该书籍 :)", "error");
}
});
})
</script>
# 关键点有两个位置:
第4行代码,每个标签添加一个属性,属性值是当前图书的主键值,为了确定删除的是哪一本书
第12行代码,这个this一定要更在点击事件之后,表示当前点击的是那个按钮,这样在30行可以方便的取出表示书籍的主键值
第33行代码,通过DOM操作将该行数据从文档节点中删除,实现页面的动态效果,用户体验度好。
后端逻辑视图函数
from django.http import JsonResponse
from app01 import models
def book_delete(request):
back_msg = {'status_code': 1111, 'msg': ''}
try:
delete_id = request.POST.get('delete_id')
models.Book.objects.filter(pk=delete_id).delete()
back_msg['msg'] = '删除成功'
except:
back_msg['status_code'] = 2222
back_msg['msg'] = '删除失败'
# 级联删除
return JsonResponse(back_msg) # 返回JsonResponse对象,自动序列化且前端自动反序列化