Ajax 局部刷新 异步提交

时间:2022-05-24 23:28:17

AJAX简介

局部刷新,异步提交。

AJAX 不是新的编程语言,而是一种使用现有标准的新方法。它最大的有点就是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

浏览器朝后端发送请求的方式:

访问方式 请求方式
浏览器地址栏输入url访问 GET请求
a标签href属性 GET请求
form表单 GET/POST请求
ajax GET/POST请求

这里的Ajax是jQuery封装之后的版本,所以在前端页面使用的时候要确保导入了jQuery。

AJAX实现局部刷新求和案例

在浏览器页面inpu框输入数字,点击提交按钮,向后端发送AJAX请求,后端计算出结果,在返回到前端页面,动态展示到第三个input框中,整个页面不刷新。

urls.py 路由
from django.conf.urls import url
from django.contrib import admin
from app01 import views urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^calculate/', views.calculate)
]
views.py
def calculate(request):
if request.is_ajax(): # 判断是否是ajax请求
# print(request.POST)
num1 = request.POST.get('num1')
num2 = request.POST.get('num2')
# 先转成整型在相加
sum_3 = int(num1)+int(num2)
# 返回的是字符串直接用HttpResponse
return HttpResponse(sum_3)
return render(request, 'calculate.html')
calculate.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>calculate</title>
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'CSS/bootstrap.css' %}"/>
<script src="{% static 'JS/bootstrap.min.js' %}"></script>
<script src="{% static 'jQuery/jquery-3.6.0.min.js' %}"></script>
{# 在前端页面使用ajax务必导入jQuery #}
</head>
<body>
<input type="text" id="inp1">+
<input type="text" id="inp2">=
<input type="text" id="inp3">
<button id="btn">计算</button>
<script>
// 先给按钮绑定一个点击事件
$('#btn').click(function (){
// 朝后端发送ajax请求
$.ajax({
// 1.指定朝哪个后端发送ajax请求
url:'', // 不写就是朝当前地址提交
// 2.请求方式
type:'post', // 不指定默认就是get 都是小写
// 3.数据 获取到两个input框的值 发送给视图层做逻辑处理
data:{'num1':$('#inp1').val(),'num2':$('#inp2').val()},
// 4.回调函数:当后端给你返回结果的时候会触发 args接收后端返回的结果
success:function(args){
// 5.通过DOM操作动态渲染到第三个input框里面
$('#inp3').val(args)
}
})
}
)
</script>
</body>
</html>

AJAX数据格式转化

ajax在实际业务中往往返回的不是字符串而是字典,那如果数据格式是字典的话,该怎样进行格式之间的转换呢?

第一种方法json

HttpResponse字典是不能直接返回的,需要将它转换成字符串格式,这时后我们就需要用到json进行序列化。

views.py
import json
def data(request):
if request.is_ajax():
print(request.POST)
# 前面加状态码是比较标准的格式
back_dic = {'code': 200, 'msg': '请求失败', 'data': {'username': 'jesse'}}
return HttpResponse(json.dumps(back_dic))
return render(request, 'data.html')

而针对后端传过来的字符串,前端是没办法对字符串化的字典进行取值操作的,所以需要在前端进行反序列化,将它变成html里面的Object类型,这样就可以用点语法将要去的值直接取出来。

data.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>calculate</title>
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'CSS/bootstrap.css' %}"/>
<script src="{% static 'JS/bootstrap.min.js' %}"></script>
<script src="{% static 'jQuery/jquery-3.6.0.min.js' %}"></script>
{# 在前端页面使用ajax无比导入jQuery #}
</head>
<body>
<input type="text" id="inp1">
<button id="btn">获取</button>
<input type="text" id="inp2">
<script>
$('#btn').click(function () {
$.ajax({
url: '',
type: 'post',
data: {'d1': $('#inp1').val()},
success:function (args){
// 反序列化 让后端发送过来的字符串变成js里面的对象
args = JSON.parse(args)
console.log(typeof args) // 返回的是object格式
// 可以针对状态码做一个判断
if (args.code == 200){
$('#inp2').val(args.data.username) // js里面的object取值就可以用点语法
}else{
alert(args.msg)
}
}
})
})
</script>
</body>
</html>

第二种方式JsonResponse

使用JsonResonse进行序列化,这样在html页面就不需要,进行反序列化了。

views.py
from django.http import JsonResponse
# 需要导一下模块 def data(request):
if request.is_ajax():
print(request.POST)
# 前面加状态码是比较标准的格式
back_dic = {'code': 200, 'msg': '请求失败', 'data': {'username': 'jesse'}}
return JsonResponse(back_dic)
return render(request, 'data.html')
data.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>calculate</title>
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'CSS/bootstrap.css' %}"/>
<script src="{% static 'JS/bootstrap.min.js' %}"></script>
<script src="{% static 'jQuery/jquery-3.6.0.min.js' %}"></script>
{# 在前端页面使用ajax无比导入jQuery #}
</head>
<body>
<input type="text" id="inp1">
<button id="btn">获取</button>
<input type="text" id="inp2">
<script>
$('#btn').click(function () {
$.ajax({
url: '',
type: 'post',
data: {'d1': $('#inp1').val()},
success:function (args){
console.log(typeof args) // 返回的是object格式
// 可以针对状态码做一个判断
if (args.code == 200){
$('#inp2').val(args.data.username) // js里面的object取值就可以用点语法
}else{
alert(args.msg)
}
}
})
})
</script>
</body>
</html

第三种方法前端指定json数据格式

$.ajax({
url: '',
type: 'post',
data: {'d1': $('#inp1').val()},
dataType:'json',
success:function (args){
// 反序列化 让后端发送过来的字符串变成js里面的对象
{#args = JSON.parse(args)#}
console.log(typeof args) // 返回的是object格式
// 可以针对状态码做一个判断
if (args.code == 200){
$('#inp2').val(args.data.username) // js里面的object取值就可以用点语法
}else{
alert(args.msg)
}

AJAX发送json格式数据

需要将数据JSON.stringify(),contentType:'application/json',序列化发送给后端。

sendjson.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>json数据</title>
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'CSS/bootstrap.css' %}"/>
<script src="{% static 'JS/bootstrap.min.js' %}"></script>
<script src="{% static 'jQuery/jquery-3.6.0.min.js' %}"></script>
</head>
<body>
<p>
<input type="text" id="inp1">
</p>
<button id="btn" class="btn btn-primary">发送</button>
<input type="text" id="inp2">
<script>
$('#btn').click(function (){
$.ajax({
url:'',
type:'post',
data:JSON.stringify({'inp1':$('#inp1').val()}),
contentType:'application/json',
success:function (res){
$('#inp2').val(res)
}
})
})
</script>
</body>
</html>
views.py
def send_json(request):
if request.is_ajax():
bytes_data = request.body # 接收到的是二进制数据
str_data = bytes_data.decode('utf-8')
print(str_data) # 转换成str类型
d = json.loads(str_data) # 转换成字典
print(type(d)) # <class 'dict'>
return HttpResponse('get it')
return render(request, 'sendjson.html')

这里需要注意的是request.POST是没办法拿到json数据的,需要使用request.body进行接收,不过接收到的是二进制数据,如果想要进一步处理,需要将数据转成字符串。再反序列化成字典。

AJAX发送文件数据

Ajax上传文件数据需要借助于JS内置的FormData对象。

upload_file.py
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传文件</title>
{% load static %}
<link rel="stylesheet" href="{% static 'CSS/bootstrap.css' %}">
<script src="{% static 'jQuery/jquery-3.6.0.min.js' %}"></script>
</head>
<body>
<input type="text" id="inp1">
<input type="file" id="inp2">
<button class="btn-primary btn">上传</button>
<script>
$('.btn').click(
function (){
// ajax上传文件需要借助内置的 FormData
var FormDataObj = new FormData();
// 1.添加普通数据
FormDataObj.append('inp1', $('#inp1').val())
// 2.添加文件数据
FormDataObj.append('inp2', $('#inp2')[0].files[0])
$.ajax({
url:'',
type:'post',
data:FormDataObj, // Django会自动识别FormData对象的数据 // 用FormData对象必须指定的参数
contentType:false, // 不指定编码格式
processData:false, // 告诉浏览器不要再处理数据 原样发回来
success:function (res){ }
})
}
)
</script>
</body>
</html>
views.py
def upload_file(request):
if request.is_ajax():
print(request.POST)
print(request.FILES)
return render(request, 'upload_file.html') # 输出结果
# <QueryDict: {'inp1': ['11111']}>
# <MultiValueDict: {'inp2': [<InMemoryUploadedFile: Snipaste_2021-08-13_15-15-54.png (image/png)>]}>

AJAX结合layer组件实现删除的二次确认

user_list.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户后台管理</title>
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'CSS/bootstrap.css' %}"/>
<script src="{% static 'JS/bootstrap.min.js' %}"></script>
<script src="{% static 'jQuery/jquery-3.6.0.min.js' %}"></script>
<script src="{% static 'layer/layer.js' %}"></script>
</head>
<body>
<div class="container-fluid">
<div class="row">
<h1 class="text-center text-primary">用户后台管理</h1>
<table class="table table-responsive table-striped">
<thead>
<tr>
<th>ID</th>
<th>用户名</th>
<th>密码</th>
<th>注册时间</th>
<th>最近登录</th>
<th>是否锁定</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for obj in user_info %}
<tr>
<td>{{ obj.id }}</td>
<td>{{ obj.username }}</td>
<td>{{ obj.password }}</td>
<td>{{ obj.date_regis }}</td>
<td>{{ obj.last_login }}</td>
<td>{{ obj.is_locked }}</td>
<td>
{# a标签是自带跳转的这里我们需要阻止跳转 给它绑定事件 #}
<a href="javascript:;" class="btn btn-danger del" del_id="{{ obj.id }}" id="del_{{ obj.id }}">删除</a>
<a href="" class="btn btn-primary">修改</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<script>
$('.del').click(function (){
var id = $(this).attr('del_id')
label_del = $(this) // 这时候的$(this)是a标签 赋值给label_del让后面能取到tr
//询问框
layer.confirm('确定删除?', {
btn: ['确定','取消'] //按钮
}, function(){
// 点击确认执行确认函数
$.ajax({
url:'',
type:'post',
data:{'id':id},
success:function (res){
if (res.code==200){
layer.msg(res.msg, {icon: 1})
label_del.parent().parent().remove() // 直接在前端页面删除一行tr标签
}else {
layer.msg(res.msg, {icon: 1})
}
}
})
});
})
</script>
</body>
</html>
views.py
from app01 import models

def user_list(request):
user_info = models.UserInfo.objects.all()
if request.is_ajax():
back_dic = {'code': 200, 'msg': '删除成功'}
# 获取前端传来的del_id
del_id = request.POST.get('id')
models.UserInfo.objects.filter(pk=del_id).delete()
return JsonResponse(back_dic)
return render(request, 'user_list.html', locals())