15 Django Ajax
一、Ajax 介绍
Ajax是一种异步提交,就是在当前页面时,不刷新当前页面的前提下,将数据提交到另一个页面
Ajax可以局部刷新页面,在一个页面下,不整体刷新页面,而是可以将当前页面的某一个部分刷新
此处回忆一下同步异步/阻塞非阻塞
同步异步:描述的任务的提交方式
同步:提交任务之后 原地等待任务的返回结果 期间不干日他的事情
异步::提交任务之后 不原地等待 直接执行下一行代码 任务结果的返回通过回调机制
阻塞非阻塞:程序的运行状态------了解程序运行的状态图
Ajax(Asynchronous Javascript And XML):翻译成中文就是“异步的 Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML)。
Ajax不是新的编程语言,而是一种使用现有标准的新方法
Ajax是一门 JS 技术,基于原生 JS 开发,但用原生的 JS 写代码太过于繁琐,我们用 JavaSquery是实现
提示:JavaSquery是基于javascript方法封装的。。。。
Ajax最大的优点:不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
二、Ajax 实例
展示一个前端页面 ,页面有三个输入框,一个提交按钮,前面两个输入框输入内容,点击按钮,同过Ajax实现点击按钮向后端提交数据,实现将前两个输入框中的数据计算和返回给第三个输入框中显示
# add_num.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<title>Title</title>
</head>
<body>
<input id="i1" type="text">+<input id="i2" type="text">=<input id="i3" type="text">
<button>Ajax提交</button>
<script>
{#1.先找到button这个对象,绑定点击事件#}
$('button').click(function () {
{#2. 触发ajax事件#}
$.ajax({
{#1. url:用来控制提交数据的地址,不写默认的是当前的地址#}
url:'',
{#2. type:用来控制向地址提交的请求,可以小写#}
type:'post',
{#3. 用来向后端提交的数据#}
data:{num1:$('#i1').val(),num2:$('#i2').val()},
{#4. 接收从后端返回的数据,也就是异步返回的结果#}
success:function(data){
{#将结果给第三个输入框#}
$('#i3').val(data)
}
})
})
</script>
</body>
</html>
# views.py文件
def add_num(request):
# 判断是否为Ajax请求
if request.is_ajax():
if request.method == 'POST':
num1 = request.POST.get('num1')
num2 = request.POST.get('num2')
data = int(num1)+int(num2)
print(data)
return HttpResponse(data)
return render(request,'add_num.html')
# url.py文件
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
# 通过Ajax向后端传数据将结果计算返回
url(r'^add/$',views.add_num,name='add_page'),
]
三、contentType 交互的数据格式
我们知道form表单,默认的向后端提交数据的编码格式是urlencoded
urlencoded:
()=()&()=()
这种就是符合urlencoded数据格式
- django后端针对
()=()&()=()
的urlencoded数据格式会自动解析,将结果打包给request.POST 用户只需要从request.POST即可获取对应信息
formdata:
- django后端针对formdata格式类型数据 也会自动解析,但是不会方法request.POST中而是给你放到了request.FILES中
ajax默认的提交数据的编码格式也是urlencoded
总结: django后端针对不同的编码格式数据 会有不同的处理机制以及不同的获取该数据的方法
四、Ajax传json格式数据
注意:在前后端进行数据交互的时候,一定要表名所发的是什么数据,是什么格式的,并且一定要遵守,表明是什么格式数据,就一定要发与之对应的数据格式。
django后端针对前端页面发送过来的 json 数据不会自动解析,会直接原封不动的给你放到request.body中,需要你手动处理,获取数据
# json.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<title>Title</title>
</head>
<body>
<input id="i1" type="text">
<input id="i1" type="text">
<button>提交</button>
<script>
$('button').click(function () {
$.ajax({
url:'',
type:'post',
data:JSON.stringify({'name':'cecilia','pwd':'123'}),
contentType:'application/json',
success:function (data) {
alert(data)
}
})
})
</script>
</body>
</html>
#views.py文件
import json
def up_json(request):
if request.is_ajax():
if request.method == 'POST':
json_bytes = request.body
json_str = json_bytes.decode('utf8')
json_dic = json.loads(json_str)
print(json_dic,type(json_dic))
return render(request,'json.html')
注意:当前端向后端发送的数据不是json格式的时候,django是默认不给看request.body中的内容的,一定要牢记,当前端向后端发送json格式数据的时候,所有的数据信息都是保存在request.body中的
在上图中可以看到,我们已经在前端页面中表明了我发的是json格式的数据,所以他提交的数据已经不在是向get和post的请求的那种()=()&()=()的形式了,所以在post自然是获取不到任何数据的了
如上图,我们点击view score的时候,我们可以看到浏览器也默认用application/json的形式来接收前端发送的数据的
五、Ajax向后端传文件
Ajax向后端传文件,需要用到内置对象Formdata
,该对象既可以传普通的键值,也可以传文件
# upload_file.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<title>Title</title>
</head>
<body>
<input type="text" name="username" id="t1">
<input type="text" name="password" id="t2">
<input type="file" name="myfile" id="t3">上传文件
<button>提交</button>
<Script>
$('button').click(function () {
// 1.先生成一个formdata对象
var myFormData = new FormData();
// 2.朝对象中添加普通的键值
myFormData.append('username',$("#t1").val());
myFormData.append('password',$("#t2").val());
// 3.朝对象中添加文件数据
// 1.先通过jquery查找到该标签
// 2.将jquery对象转换成原生的js对象
// 3.利用原生js对象的方法 直接获取文件内容
myFormData.append('myfile',$('#t3')[0].files[0]);
$.ajax({
url:'',
type:'post',
data:myFormData, // 直接丢对象
// ajax传文件 一定要指定两个关键性的参数
contentType:false, // 不用任何编码 因为formdata对象自带编码 django能够识别该对象
processData:false, // 告诉浏览器不要处理我的数据 直接发就行
success:function (data) {
alert(data)
}
})
})
</Script>
</body>
</html>
# views.py文件
def upload_file(request):
# 判断请求是否为Ajax请求
if request.is_ajax():
if request.method == 'POST':
print(request.POST) # 这里只是收到了普通的键值对
print(request.FILES) # 上传的文件的对象在这里
return HttpResponse('收到')
return render(request,'upload_file.html')
注意:
-
利用formdata对象 能够简单的快速传输数据 (普通键值 + 文件)
-
有几个参数
data:formdata # 对象 contentType:false # 不用任何编码 因为formdata对象自带编码 django能够识 processData:false # 告诉浏览器不要处理我的数据 直接发就行
六、给前端返回一个字典
将用户表的数据 查询出来 返回给前端
给前端的是一个大字典 字典里面的数据的一个个的字段
# dict.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<title>Title</title>
</head>
<body>
{{user_list}}
{#这是最原始的利用模板语法来接收的大字典#}
{#{% for user_obj in user_list %}#}
{# <p>username:{{ user_obj.username }} age: {{ user_obj.age }} gender: {{ user_obj.gender }}</p>#}
{#{% endfor %}#}
</body>
</html>
# views.py文件
from app01 import models
from django.core import serializers
def back_dic(request):
user_obj_list = models.UserInfo.objects.all()
# 1.原始的方式向前端页面传送字典
# user_list = []
# for user_obj in user_obj_list:
# user_list.append({
# 'username':user_obj.username,
# 'age':user_obj.age,
# 'gender':user_obj.get_gender_display()
# })
# 2. 利用serializers这个模块来帮我们很简单的将对象变为字典
'''
serializers:模块有两个参数
1.format:代表序列成什么格式的数据
2.queryset:要序列化的对象
'''
user_list = serializers.serialize('json',user_obj_list)
return render(request,'dict.html',locals())
七、Ajax + sweetalert
下面我们要做的一个案例就是这个sweetalert的一个二次确认框
# sweet.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<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>
<link rel="stylesheet" href="{% static 'sweetalert/dist/sweetalert.css' %}">
<script src="{% static 'sweetalert/dist/sweetalert.js' %}"></script>
<meta name="viewport" content="width=device-width, initial-scale=1 ">
<title>Title</title>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-8 col-md-offset-2">
<h2>数据展示</h2>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<td>序号</td>
<td>姓名</td>
<td>年龄</td>
<td>性别</td>
<td class="text-center">编辑</td>
</tr>
</thead>
<tbody>
{% for user_obj in user_obj_list %}
<tr>
<td>{{forloop.counter }}</td>
<td>{{user_obj.username }}</td>
<td>{{user_obj.age}}</td>
<td>{{user_obj.get_gender_display}}</td>
<td>
<a href="#" class="btn btn-success">编辑</a>
<a href="#" class="btn btn-warning cancel" del_id="{{ user_obj.pk }}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<script>
$('.cancel').click(function () {
var $btn = $(this);
swal({
title: "你确定要删吗?",
text: "你要是删了,你就准备好跑路吧!",
type: "warning",
showCancelButton: true, //这是确定俺就
confirmButtonClass: "btn-danger",
confirmButtonText: "对,老子就要删!", //确定按钮的文本
cancelButtonText: "算了,算了!", //这是取消删除的文本内容
closeOnConfirm: false,
showLoaderOnConfirm: true//实现确定按钮后的加载后删除
},
function(){
$.ajax({
url:'',
type:'post',
data:{'delete_id':$btn.attr('delete_id')},
success:function (data) {
if (data.code){
swal(data.msg, "你可以回去收拾行李跑路了.", "success");
// 1.直接刷新页面
{#window.location.reload()#}
// 2.通过DOM操作 实时删除
$btn.parent().parent().remove()
}else{
swal("发生了未知错误!", "我也不知道哪里错了.", "info");
}
}
});
});
})
</script>
</body>
</html>
# views.py文件
import time
from django.http import JsonResponse
def sweetalert(request):
# 如果是get请求,就把用户对象返回给前端页面
user_obj_list = models.UserInfo.objects.all()
# 如果是POST请求,就删除需要删除的用户对象
if request.method == 'POST':
# 先定义一个字典,作为返回给前端页面的
back_dic = {"code":True,'msg':''}
delete_id = request.POST.get('delete_id')
models.UserInfo.objects.filter(pk=delete_id).delete()
back_dic['msg'] = '后端传来的:真的被我删了'
time.sleep(3)# 这里是实现一个加载一段时间后删除
return JsonResponse(back_dic)
return render(request,'sweet.html',locals())
补充:
1.上述的样式类部分渲染的样式来自于bootstrap中,所有建议在使用上述样式时,将bootstrap的js和css也导入了,这样的情况下,页面效果就不会有任何问题
2.弹出的上述模态框中,可能字体会被图标掩盖一部分,可通过调整字体的上外边距来解决
八、Ajax 实例
7.1 input框失去焦点事件
在注册表单中,当用户填写了用户名后,把光标移开后,会自动向服务器发送异步请求。服务器返回这个用户名是否已经被注册过。
# register.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<title>Title</title>
<style>
.aa{
margin-top: 20px;
}
.bb{
display: none;
}
</style>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-sm-2 col-sm-offset-5" style="background-color: #dca7a7;margin-top: 50px">
<div>
<input class="form-control aa" type="text" name='username' value="输入用户名" id="i1">
</div>
<p><span class="bb aa" style="color: red">用户名已存在</span></p>
<div>
<input class="form-control aa" type="text" name='pwd' value="输入密码" id="i2">
</div>
{# <div>#}
{# <input class="form-control aa" type="text" name='repwd' value="确认密码" id="i3">#}
{# </div>#}
<div class="text-center">
<input class="aa" type="radio" name='gender' value="1" id="i4">男
<input class="aa" type="radio" name='gender' value="2" id="i5" checked>女
</div>
<div class="text-center">
<button class="btn aa">注册</button>
</div>
</div>
</div>
</div>
<script>
// 用户名输入框的失去焦点事件
$('#i1').blur(function () {
$.ajax({
url:'',
type:'post',
data:{'username':$(this).val()}, //this代表的是当前的jq对象
success:function (data) {
back_dic=JSON.parse(data);//反序列化从后端传回来的数据
if (back_dic['flag']){
// 如果条件存在,就将标签的bb类属性去掉
$('p>span').removeClass('bb');
}
}
})
})
</script>
</body>
</html>
# views.py文件
def register(request):
if request.method == 'POST':
# 先定义一个字典,用于给前端返回数据
back_dic = {'flag': False}
# 拿到前端的post请求携带的参数
username = request.POST.get('username')
# 从数据库中取这个username名的对象
user_obj = models.UserInfo.objects.filter(username=username).first()
if user_obj:
# 如果这个对象存在
back_dic['flag'] = True
import json
# 将返回序列化号的json格式的数据返回给前端页面
return HttpResponse(json.dumps(back_dic))
return render(request,'register.html')