Ajax+layer
# Ajax简介
精髓: 局部刷新,异步提交. -- 刻在心里.
唠唠嗑: 一个网址首页的访问量最大,一般不会让新手做,里面涉及到很多细节,要考虑高并发的情况.. 访问量一大,同一功能采取的实现方案就不一样啦.这就是大厂与其它公司的区别.
AJAX (Asynchronous Javascript And XML) 翻译成中文就是“异步的Javascript和XML”.
AJAX 不是新的编程语言, 而是一种使用现有标准的新方法.它使用JavaScript技术向服务器发送异步请求;
AJAX请求无须刷新整个页面, 服务器响应内容不再是整个页面,而是页面中的部分内容,性能高!
即在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容!
这一特点给用户的感受是在不知不觉中完成请求和响应过程.
典型的应用场景:
注册时候的用户名的查重..若已经占用会提示.需要注意,这一整个过程页面并没有刷新!
微博页面一直下滑,可以发现下滑几个微博之后,再向下就没有了,转而会出现一个加载的动画,不一会儿下方就继续出现了新的微博内容,这个过程其实就是 Ajax 加载的过程...
form表单的提交一般会进行页面的跳转(不成功时跳转到当前页面), 而有时我们是对弹出框进行数据提交,希望提交成功则关闭弹出框并刷选父页面,失败则提示失败原因,且弹出框不关闭.此时可采用ajax进行数据提交.
用pycharm创建一个名为ajax的django项目,并在该项目中创建一个名为app01的应用.
记得改模版的路径设置 'DIRS': [os.path.join(BASE_DIR, 'templates')],
暂且把中间件的csrf验证给注释掉!不然post请求会报错.
# 小案例-发送Ajax请求
通过该小案例学会Ajax发送请求!! -- 实现页面不刷新计算结果.
专业的前端需要知道如何用原生的js实现Ajax,但我们不需要,我们直接使用jQuery封装好的Ajax就行!
get方式渲染得到页面,在该页面输入数字,点击计算按钮,触发点击事件,将输入采用ajax的post请求方式异步提交数据给后端!!后端将得到的str类型数据进行转型相加处理,并返回给前端页面!!
如果不这样做,就需要用form表单提交数据到后端,后端render(..,..,locals())到同一html页面..页面刷新啦!!
有点类似于前面单表(用户表数据)的修改功能的实现..
当然最简单的实现方案是在前端用js将输入进行相加得到结果,为了学习ajax嘛!!就没这样做!
扩展:若想实现将输入框的输入内容改变,不点击计算按钮,显示的结果同步改变!需要添加键盘事件,改变输入值自动发送ajax请求..略
ajax.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'^index/', views.index),
]
2
3
4
5
6
7
8
9
app01.views.py
from django.shortcuts import render, HttpResponse
def index(request):
# print(request.POST)
if request.is_ajax():
d1 = request.POST.get('d1')
d2 = request.POST.get('d2')
d3 = int(d1) + int(d2)
return HttpResponse(d3)
return render(request, "index.html")
2
3
4
5
6
7
8
9
10
11
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<title>Title</title>
</head>
<body>
<div style="padding: 20px">
<input type="text" id="d1">
+
<input type="text" id="d2">
=
<input type="text" id="d3">
<button class="btn">计算</button>
</div>
<script>
// -- jquery绑定点击事件
$('.btn').click(function () {
// -- $('#d1')选中对应的input框,val()不传值代表获取值
var d1 = $('#d1').val()
var d2 = $('#d2').val()
// -- $符号指的就是jquery对象!往ajax方法里传递一个对象{}.
$.ajax({
// 1.指定数据提交的路径/路由地址.若为空则为当前路径
url: '', // -- 这里等同于/index/
// 2.指定提交方式 get、post、put、delete
type: 'post',
// 3.往后端提交的数据
data: {'d1': d1, 'd2': d2},
// 4.接收后端返回的结果
// 并不是点击'计算'按钮时执行,而是当后端返回结果时,会自动触发执行.
// 它会将结果传递给res这个形参,即res就是后端返回的结果
success: function (res) {
// alert(res)
// val传值代表赋值
$('#d3').val(res)
}
})
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# 小案例-Ajax发送json数据
学会通过Ajax发送json格式数据
最终效果跟上方的小案例一摸一样!!!C端Ajax发送json数据,S端接收..
index.html
data: JSON.stringify({'d1': d1, 'd2': d2}),
contentType: 'application/json',
数据提交的编码方式,form表单可以提交两种,但json格式的数据提交不了.ajax可以发送json格式的数据..
<body>
<div style="padding: 20px">
<input type="text" id="d1">
+
<input type="text" id="d2">
=
<input type="text" id="d3">
<button class="btn">计算</button>
</div>
<script>
$('.btn').click(function () {
var d1 = $('#d1').val()
var d2 = $('#d2').val()
$.ajax({
url: '',
type: 'post',
data: JSON.stringify({'d1': d1, 'd2': d2}), // ★
contentType: 'application/json', // ★
success: function (res) {
$('#d3').val(res)
}
})
})
</script>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
app01.views.py
request.POST拿到POST请求的数据, 但该数据不包含文件数据、以及json格式的数据!!
json格式的数据,后端需要通过 request.body
的形式取到!
def index(request):
if request.is_ajax():
# json_bytes -- b'{"d1":"1","d2":"8"}' -- bytes类型
json_bytes = request.body
# json_str -- {"d1":"1","d2":"8"} -- str类型
json_str = json_bytes.decode('utf-8')
# dict_data -- {'d1': '1', 'd2': '8'}
dict_data = json.loads(json_str)
d1 = dict_data.get('d1')
d2 = dict_data.get('d2')
d3 = int(d1) + int(d2)
return HttpResponse(d3)
return render(request, "index.html")
2
3
4
5
6
7
8
9
10
11
12
13
# Ajax接收后端返回数据
S端发送json数据,C端接收..
★ 什么时候前端不需要对接收的数据反序列化??!!
return JsonResponse(back_dic)
、$.ajax({..,dataType: 'json',..})
有其一,就可不用反序列化.
下方代码展示前端需要反序列化的情况!!
app01.views.py
from django.shortcuts import render, HttpResponse
from django.http import JsonResponse
import json
def index(request):... ...
def train(request):
if request.is_ajax():
back_dic = {
"code": 200,
"msg": "请求成功!",
"data": {'user name': 'egon', 'age': 20}
}
return HttpResponse(json.dumps(back_dic))
# return JsonResponse(back_dic)
return render(request, "train.html")
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
train.html
json格式的数据如何取值? 直接点语法!!!!!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<title>Title</title>
</head>
<body>
<div style="padding-left:200px;padding-top:10px">
<button class="btn">计算</button>
</div>
<script>
$('.btn').click(function () {
$.ajax({
url: '',
type: 'post',
data: '',
// dataType: 'json',
success: function (res) {
console.log(typeof res) // string
// 将json类型的数据反序列化为js的对象
res = JSON.parse(res)
if (res.code == 200) {
alert(res.msg + '\n' + res.data + '\n' + res.data.age)
} else {
alert(res.msg)
}
}
})
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# Ajax上传文件
学会通过Ajax发送文件数据到后端!! 需要借助js里的FormDate对象!
扩展思考,上传图片,会在前端页面展示出来.. 如何实现?略.
file.html
<body>
<br>
<div style="margin-left: 10px">
<p><input type="text" id="d1"></p>
<p><input type="file" id="d2"></p>
<button class="btn">上传</button>
</div>
<script>
console.log($("#d2"))
$('.btn').click(function () {
var d1 = $('#d1').val()
// ★ -- ajax上传文件数据,需要借助JS内置的FormDate对象!!
// Ps:FormData中,一条k-v对应一条数据,key值是唯一的,一个key值可以对应多条value值..
var formDataObj = new FormData() // 创建一个空的FormDate对象.
// 1) 添加普通数据
formDataObj.append('d1', d1)
// 2) 添加文件数据
// $("#d2")[0].files[0] 拿到文件对象!!
formDataObj.append('d2', $("#d2")[0].files[0])
$.ajax({
url: '',
type: 'post',
data: formDataObj, // django会自动识别FormDate对象的数据
// ★ -- 注意!用FormDate对象有两个必须指定的参数!!!
contentType:false, // -- 不指定编码格式
processData:false, // -- 告诉浏览器不要处理我的数据
success: function (res) { }
})
})
</script>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
app01.views.py
def upload_file(request):
if request.is_ajax():
# <QueryDict: {'d1': ['123456']}>
print(request.POST)
# <MultiValueDict: {'d2': [<InMemoryUploadedFile: 111.jpg (image/jpeg)>]}>
print(request.FILES)
return render(request, "file.html")
2
3
4
5
6
7
# ajax+layer !!
★ ajax结合layer组件实现删除的二次确认!!
-- 前后端混合开发的场景下这个知识点会用很多次!
# layer的使用
layer官网: https://www.layuiweb.com/layer/index.htm
step1> 官网下载layer组件,解压放到Django根目录下的static文件夹里.并在settings.py里配置相关属性.
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
2
3
4
step2> 在html页面引入jquery和layer.js.. (注意先后,jquery在前,layer.js在后)
<head>
<meta charset="UTF-8">
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<title>Title</title>
{% load static %}
<script src="{% static 'layer-v3.5.1/layer/layer.js' %}"></script>
</head>
2
3
4
5
6
7
8
9
如何使用,具体查看官网的文档手册!!
# 删除二次确认
展示用户列表,删除第一条数据.
点击确定删除
删除成功
页面自动更新/删除对应的dom元素
app01.models.py
from django.db import models
class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32)
2
3
4
5
6
app01.views.py
from django.shortcuts import render
from django.http import JsonResponse
from app01 import models
def show_user(request):
if request.is_ajax():
back_dic = {
'code': 200,
'msg': '删除成功!'
}
id = request.POST.get('id')
models.User.objects.filter(pk=id).delete()
return JsonResponse(back_dic)
user_list = models.User.objects.all()
return render(request, 'show_user.html', locals())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
show_user.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<title>Title</title>
{% load static %}
<script src="{% static 'layer-v3.5.1/layer/layer.js' %}"></script>
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-md-6 col-md-offset-1">
<table class="table table-hover table-striped">
<thead>
<tr>
<th>ID</th>
<th>username</th>
<th>password</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for obj in user_list %}
<tr>
<td>{{ obj.id }}</td>
<td>{{ obj.username }}</td>
<td>{{ obj.password }}</td>
<td>
{# 去除掉a标签原本的href功能,让其失效. #}
{# ★这里不能直接id='del',因为循环出来就重复了!!#}
{# 但可以通过拼接id保证不重复!!虽然本案例中并没有用到id选择器. #}
{# del_id 是自定义属性,保证我们能否拿到要删除数据的id!! #}
<a href="javascript:" class="btn btn-danger del" \
id="del_{{ obj.id }}" del_id="{{ obj.id }}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<script>
$('.del').click(function () {
// 拿到要删除数据的id!! this指向当前对象,这里是a标签.
var id = $(this).attr('del_id')
var currentBtn = $(this)
layer.confirm('您确定删除吗?', {
btn: ['确定']
}, function () {
$.ajax({
url: '',
type: 'post',
data: {'id': id},
success: function (res) {
if (res.code == 200) {
// icon:1 是绿色的勾; icon:2 是红色的叉
/* --
{# ★★★ 方案一,删除成功后,帮用户执行下刷新!#}
layer.msg(res.msg, {icon: 1}, function () {
// 让弹出框显示两秒后,在执行这个回调函数,刷新页面!
location.reload()
});
// location.reload() // 放在这效果不好.
-- */
{# ★★★ 方案二,删除成功后,进行DOM操作,删除当前页面tr这个dom元素!#}
layer.msg(res.msg, {icon: 1})
// -- 失败,这里this指向的是success函数
// $(this).parent().parent().remove()
currentBtn.parent().parent().remove()
} else {
layer.msg(res.msg, {icon: 2})
}
}
})
}
);
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# 实现loading层
实验结果:
点击‘‘加载’‘按钮, 会发送ajax的post请求, 在发送之前,会加载layer的loading层!
当ajax接收到后端返回的结果后,关闭layer的loading层..
views.py
import time
from django.http import JsonResponse
def loading(request):
time.sleep(3) # -- 模拟网络延迟
if request.method == "POST":
username = request.POST.get('username')
return JsonResponse({'username': username})
return render(request, 'loading.html')
2
3
4
5
6
7
8
9
10
loading.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
<title>Title</title>
{% load static %}
<script src="{% static 'layer-v3.5.1/layer/layer.js' %}"></script>
</head>
<body>
<button class="btn">加载</button>
<script>
var index; // 定义index为全局变量
$('.btn').click(function () {
$.ajax({
url: '',
type: 'post',
data: {'username': 'egon', 'csrfmiddlewaretoken': '{{ csrf_token }}'},
// 在发送ajax之前执行的!
beforeSend: function () {
// loading层
index = layer.load(1, {
shade: [0.1, '#fff'] //0.1透明度的白色背景
});
},
success: function (res) {
// 关闭
layer.close(index)
}
})
})
</script>
</body>
</html>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37