Django与Ajax
Ajax简介
AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。
Ajax基本语法结构
$.ajax({
代码块
})
使用Ajax的例子,页面输入两个整数,在不刷新浏览器的情况下传输到后端计算出结果
urls.py:
url(r'^ajax_test/', views.ajax_test),
views.py:
from django.shortcuts import render,HttpResponse
# Create your views here.
def ajax_test(request):
if request.method == 'POST':
d1 = request.POST.get('d1')
d2 = request.POST.get('d2')
d3 = int(d1) + int(d2)
return HttpResponse(d3)
return render(request,'ajax_test.html')
ajax_test.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</head>
<body>
<input type="text" id="d1"> + <input type="text" id="d2"> =
<input type="text" id="d3">
<button id="d4">点我发送ajax数据</button>
<script>
// 重点
$('#d4').click(function () {
$.ajax({
url:'', //数据提交的后端地址,跟form表单的action参数一样
type:'post', //提交方式为post,默认也是get请求
data:{'d1':$('#d1').val(),'d2':$('#d2').val()}, //提交的数据
success:function (data) { //形参data就是异步提交给后端,后端通过计算返回的结果,回调函数
$('#d3').val(data) // 回调之后做的事情,设置值。
}
})
})
</script>
</body>
</html>
如果使用了ajax,视图层的三板斧都不会再与前端页面交互,而是与回调函数的形参data交互。
前后端传输的编码格式
发送请求的前端标签
我们所学过的向后端发送请求的前端标签都有哪些?
- a标签: get请求,get请求也可以携带参数,?xxx=111&yyy=222
- form表单:get/post请求
- ajax:get/post请求
针对这些前端发送post请求的我们来研究一下它们的数据在前端的编码格式:
前端交互是一个数据编码格式,针对不同的数据,后端会进行不同的处理。
比如说django后端有
- request.POST
- request.FILES
那么为什么只要是POST请求,就会交给request.POST进行处理,如果是文件请求,就会交给request.FILES进行处理,我们带着这些疑问来往下看。
前端三种数据格式
在前端呐,有三种数据格式:
- urlencoded
- formdata
- application/json
针对上面所学过的向后端发送请求的前端标签来看
form表单发送三种数据格式的情况
form表单只能够发送两种数据格式的数据:1和2
1.form表单post请求默认的编码格式是urlencoded
在浏览器-->检查-->network可以看到,我们form表单在提交数据的时候,有如下信息
Request Headers: # 请求头
Content-Type:application/x-www-form-urlencoded; charset=UTF-8 # 数据编码格式-urlencoded
Form Data:# 携带的数据
d1=232323&d2=23232132
在我们后端django中针对urlencoded数据,会自动解析并封装到request.POST方法中。
2.form表单如果发送文件
Request Headers: # 请求头
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryhjKCHQHDmcE62iMQ # 数据编码格式,-form-data
Form Data:#针对form-data格式的数据,在浏览器是无法查看的。
发送到后端django,文件对象会自动解析到 request.POST 和 request.FILES 中,前者记录文件名,后者记录对象。
3.form表单无法发送json格式的数据,如果发的话,只能借助于ajax
ajax三种编码格式都能够发送
ajax能够发送三种数据格式的数据:1、2和3
1.ajax默认的编码格式也是urlencoded,django后端也是将数据封装到request.POST中
那么我们刚才看了form表单发送这些默认编码格式的数据,还有一个发送json格式的需要借助于ajax,请继续往下看
2.Ajax传输json格式数据
urls.py:
url(r'^form_test/', views.form_test),
views.py:
def form_test(request):
if request.method == "POST":
print(request.body)
json_bytes = request.body
print(json.loads(json_bytes),type(json.loads(json_bytes)))
# 反序列化为python字典格式
return render(request,'form_test.html')
打印结果:
b'{"username":"qinyj","pwd":123}' # request.body
{'username': 'qinyj', 'pwd': 123} <class 'dict'> # 反序列化之后的
form_test.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</head>
<body>
<form action="" method="post">
username: <input type="text" name="username" id="d1">
password: <input type="text" name="password" id="d2">
# 这里不要用form表单的提交,为什么呢,因为form表单提交的默认数据编码格式是urlencoded,也会将json格式的数据封装到后端request.body中
</form>
<button id="d3">点我发送json格式</button>
<script>
$('#d3').click(function () {
$.ajax({
url:'',
type:'post',
contentType:'application/json', //需要指定编码格式为json
data:JSON.stringify({'d1':$('#d1').val(),'d2':$('#d2').val()}), // 需要前端发送JSON字符串,JSON。stringify序列化即可。
success:function (data) {
alert(123) // 此弹框仅仅演示,没有任何用户
}
})
})
</script>
</body>
</html>
django后端针对前端json格式的数据,不会做任何处理,数据怎么来的,原封不动的封装到request.body
中(基于网络传输二进制的json字符串),需要自己处理格式
3.Ajax传输文件数据
views.py:
def form_test(request):
if request.method == "POST":
print(request.POST)
print(request.FILES)
# 前端上传文件之后打印结果
# < QueryDict: {'username': ['qinyj']} >
# < MultiValueDict: {'myfile': [ < InMemoryUploadedFile: Devops工具链.png(image / png) >]} >
return render(request,'form_test.html')
form_test.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
{% load static %}
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<script src="{% static 'bootstrap/js/bootstrap.min.js' %}"></script>
</head>
<body>
<form action="">
file: <input type="file" name="file" id="d1">
</form>
<button id="d4">点我发送文件格式的数据</button>
<script>
$('#d4').click(function () {
// 先生成一个内置对象
var MyFormData = new FormData();
// 添加普通的键值对
MyFormData.append('username','qinyj');
// 添加文件数据
MyFormData.append('myfile',$('#d1')[0].files[0]);
$.ajax({
url:'',
type:'post',
data:MyFormData,
// 发送文件必须要指定的两个参数
contentType:false, // 不适用任何编码,MyFormData对象内部自带编码,django后端能够识别。
processData:false, // 不处理任何数据
success:function (data) {
}
})
})
</script>
</body>
</html>
django 能够识别前端ajax发送过来的文件对象,并放入对应的方法中request.FILE
去解析。
序列化的概念
在前端分离的场景下,发送给前端json格式的字符串形式,再写上说明文档,方便数据交互
我们可以手动在后端将数据转成json字符串格式,django非常友好,帮我们想到了这一点,需要借助一个模块来完成。
from django.core import serializers
urls.py:
url(r'^get_data/', views.get_data),
views.py:
# 需要导入模块
from django.core import serializers
from app01 import models
def get_data(request):
# 从数据库中查出来所有的信息,
# 序列化目的,将数据整合成一个大字典形式,
user_querset = models.User.objects.all()
res = serializers.serialize('json',user_querset)
return HttpResponse(res)
# 前端页面接收到的json数据:
[{"model": "app01.user", "pk": 1, "fields": {"username": "qinyj", "password": 123, "gender": 1}}, {"model": "app01.user", "pk": 2, "fields": {"username": "jack", "password": 123, "gender": 2}}]
Ajax常见应用场景
搜索框中根据用户输入的关键字,自动提示检索关键字
用户的注册时候的查重
sweetalert插件
上述弹窗效果代码链接 https://lipis.github.io/bootstrap-sweetalert/
模板层
需要引入sweetalert.js文件:
将下载好的项目里面的dist文件夹放到static目录中即可,就只需要用到这个文件夹中的内容
<link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}">
<script src="{% static 'dist/sweetalert.min.js' %}"></script>
<a href="#" class="btn btn-danger del">删除</a>
给删除按钮添加一个点击事件:
<script>
$(".del").click(function () {
{#先拿到当前被点击的对象#}
var $btn = $(this);
{#去找删除按钮效果代码 #}
swal({
title: "你确定?",
text: "你如果删除了,你就准备跑路吧",
type: "warning",
showCancelButton: true,
confirmButtonClass: "btn-danger",
confirmButtonText: "确定",
cancelButtonText: "取消",
closeOnConfirm: false,
closeOnCancel: false,
{#让操作有个延时的...的操作#}
showLoaderOnConfirm: true
},
function (isConfirm) {
if (isConfirm) {
{#朝后端发送ajax请求 做一些操作#}
$.ajax({
url:'',
type:'post',
data:{'delete_id':$btn.attr('delete_id')},
success:function (data) {
if (data.code==200){
swal("准备跑路吧", data.msg, "success");
{#通过DOM操作,操作标签 移除标签#}
$btn.parent().parent().remove()
} else {
swal("Error", "出现了未知Bug", "warning");
}
}
});
} else {
swal("取消", "我怂了)", "error");
}
});
})
</script>
视图层
import time
from django.http import JsonResponse
def boot_list(request):
# 判断是否是ajax请求,如果是的话走下面的判断。
if request.is_ajax():
# 若ajax与服务器进行交互,通常后端是返回给ajax一个字典信息的。
back_dic = {'code':200,'msg':''}
delete_id = request.POST.get('delete_id')
time.sleep(1)
models.Book.objects.filter(pk=delete_id).delete()
back_dic['msg'] = "删除成功"
return JsonResponse(back_dic)