DC's blog DC's blog
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)

DC

愿我一生欢喜,不为世俗所及.
首页
  • 计算机基础
  • linux基础
  • mysql
  • git
  • 数据结构与算法
  • axure
  • english
  • docker
  • opp
  • oop
  • 网络并发编程
  • 不基础的py基础
  • 设计模式
  • html
  • css
  • javascript
  • jquery
  • UI
  • 第一次学vue
  • 第二次学vue
  • Django
  • drf
  • drf_re
  • 温故知新
  • flask
  • 前后端不分离

    • BBS
    • 订单系统
    • CRM
  • 前后端部分分离

    • pear-admin-flask
    • pear-admin-django
  • 前后端分离

    • 供应链系统
  • 理论基础
  • py数据分析包
  • 机器学习
  • 深度学习
  • 华中科大的网课
  • cursor
  • deepseek
  • 杂文
  • 罗老师语录
  • 关于我

    • me
  • 分类
  • 归档
GitHub (opens new window)
  • Django

    • 框架引入
    • 基本配置
    • 单表记录CURD
    • 路由和视图层
    • 模版层
    • ORM查询
    • ORM字段
    • Ajax+layer
      • Ajax简介
      • 小案例-发送Ajax请求
      • 小案例-Ajax发送json数据
      • Ajax接收后端返回数据
      • Ajax上传文件
      • ajax+layer !!
        • layer的使用
        • 删除二次确认
        • 实现loading层
    • 自定义分页器
    • cookie与session
    • 中间件和csrf
    • Auth认证模块
    • ORM复习
    • 测试Demo
  • 第一次学drf

  • 第二次学drf

  • 温故知新

  • flask

  • 后端
  • Django
DC
2023-03-14
目录

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),
]
1
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")
1
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>
1
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>
1
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")
1
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")
1
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>


1
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>
1
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")
1
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')
]
1
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>
1
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)
1
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())
1
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>
1
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')
1
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>
1
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


ORM字段
自定义分页器

← ORM字段 自定义分页器→

最近更新
01
deepseek本地部署+知识库
02-17
02
实操-微信小程序
02-14
03
教学-cursor深度探讨
02-13
更多文章>
Theme by Vdoing | Copyright © 2023-2025 DC | One Piece
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式