Ajax技术+layer弹窗
一、Ajax技术简介
1、AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”。
即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。
局部刷新、一步提交
2、作用
前端技术,把前端的数据提交到后端的。Ajax技术就是局部刷新,异步提交,它不需要刷新整个页面,只需要刷新局部的,主要就是刷新的时候是无感知的
3、案例
html 前端页面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.4/jquery.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script> </head> <body> <input type="text" name="" id="d1">+ <input type="text" name="" id="d2">= <input type="text" name="" id="d3"> <button class="btn btn-info">计算</button> <script> $(".btn").click(function() { // 获取输入框中的内容 var d1 = $("#d1").val(); var d2 = $("#d2").val(); // 前端数据提交到后端 $.ajax({ // 1、提交到哪里 url: "", // 2、要指定请求方式提交 type: "post", // 3、指定要传递的数据 data: {'d1':d1,'d2':d2}, // 4、回调函数, 接收后端返回的数据 success : function(res){ {#console.log(res);#} $("#d3").val(res) } }) }) </script> </body> </html>
注意:Ajax 提交数据到后端的4个步骤
$.ajax({ url:'/index/?a=1&b=2', type:'post', data:{'a':1, b:2} success:function(res) { # res:什么时候反序列化,什么时候不反序列化 console.log(res.username) console.log(res.data.password) } })
$.ajax({ }) ajax的调用,
后端返回的数据给res,大多数情况下,后端返回的数据直接就是json格式,如果是json格式的,就不用反序列化了
如果返回的是JSON格式的字符串,就需要反序列化
后端视图函数:
def index(request): if request.method == 'POST': # 接收参数 d1 = request.POST.get('d1') d2 = request.POST.get('d2') # 做运算 d3 = int(d1) + int(d2) return HttpResponse(d3) # 返回给res return render(request, 'index.html')
注意⚠️后端返回数据的多种情况:
第一种:
当后端返回的值 res为string类型时,即 return HttpResponse(d3)。前端html页面可以直接使用。
前端自行反序列化 JSON.parse()后可以改变类型,比如前端传来的d3是一个string,JSON.parse()后是number。
success : function(res){ res = JSON.parse(res); console.log(res); console.log(res.code); {#$("#d3").val(res)#} }
没有反序列化:前端能直接使用后端传来的string数据
反序列化以后:反序列化之后依旧可以直接使用,数据类型变为number
第二种:
后端直接返回 JsonResponse()数据,前端不需要在反序列化,可以直接取值。
JsonResponse()返回的数据就是json数据
# 后端 from django.http import JsonResponse def index(request): if request.method == 'POST': d = {'code': 200, 'meg': '请求成功', 'data': {'username': 'jingzhi'}} return JsonResponse(d) return render(request, 'index.html') # 前端 $.ajax({ // 1、提交到哪里 url: "", // 2、要指定请求方式提交 type: "post", // 3、指定要传递的数据 data: {'d1':d1,'d2':d2}, // 4、回调函数, 接收后端返回的数据 success : function(res){ console.log(res); console.log(res.code); console.log(res.meg); } })
第三种:
后端序列化后使用HttpResponse()方式,前端需要指定数据类型dataType: "json",
# 后端 def index(request): if request.method == 'POST': d = {'code': 200, 'meg': '请求成功', 'data': {'username': 'jingzhi'}} import json res = json.dumps(d, ensure_ascii=False) # res序列化为字符串 return HttpResponse(res) # 返回给res return render(request, 'index.html') # 前端 $.ajax({ // 1、提交到哪里 url: "", // 2、要指定请求方式提交 type: "post", // 3、指定要传递的数据 data: {'d1':d1,'d2':d2}, dataType: "json", // 4、回调函数, 接收后端返回的数据 success : function(res){ console.log(res); console.log(res.code); console.log(res.meg); } })
二、
要满足的两个条件
1. 你传的数据一定要是json格式的
2. 一定要把ajax默认提交的urlencode改为'application/json'
1、html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script> </head> <body> <button class="btn btn-info">按钮</button> <script> $(".btn").click(function () { $.ajax({ url: '/index/', type: 'post', data: JSON.stringify({a1: 1, a2: 2}), contentType : 'application/json', success: function (res) { console.log(res) } }) }) </script> </body> </html>
2、views
from django.shortcuts import render import json # Create your views here. def index(request): print(request.body) # b'{"a1":1,"a2":2}' json_str = json.loads(request.body) # json.loads 能够自动进行二进制解码,然后再反序列化 print(json_str.get('a1')) return render(request, 'index.html')
注意:
1. 针对ajax提交的json格式的数据,django后端不在把数据封装到request.POST中了。
2. 前端发送json数据的前提:数据进行序列化、指定内容类型
data: JSON.stringify({a1: 1, a2: 2}), contentType : 'application/json',
3、后端拿到数据是纯原生的,发送过来的数据是二进制形式的,后端需要解码、反序列化
三、
1、html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script> </head> <body> <form action=""> username: <input type="text" id="username"> password: <input type="password" id="password"> 文件: <input type="file" id="my_file"> <button class="btn btn-primary">提交</button> {# 两次提交,提交按钮可以放到form表单外#} </form> {#<button class="btn btn-info">按钮</button>#} <script> $(".btn").click(function (event) { // 拿普通数据 var username = $("#username").val(); var password = $("#password").val(); // 拿文件数据 {#var my_file = $("#my_file"); {#产生一个jq对象,在浏览器控制台可以查看#} {#console.log(my_file);#} var myfile = $("#my_file")[0].files[0]; {#console.log(myfile);#} // 发送文件数据到后端需要借助于FormData对象 var myFormDataObj = new FormData(); myFormDataObj.append('username', username); myFormDataObj.append('password', password); myFormDataObj.append('myfile', myfile); $.ajax({ url: '/index/', type: 'post', data: myFormDataObj, contentType:false, // 告诉浏览器不要做任何的编码格式处理,django自己来做处理 processData:false, // 告诉浏览器不要对我处理的数据做任何的处理 success: function (res) { {#console.log(res)#} } }); event.preventDefault(); {#阻止后续提交第一种方式#} {#return false #} {#阻止后续提交第二种方式#} }) </script> </body> </html>
关于 var myfile = $("#my_file")[0].files[0]; 的补充
$("#my_file")
返回一个包含匹配元素的数组。由于我们只对一个元素感兴趣,通过 [0]
来获取这个元素。
.files[0]
: 一旦我们有了文件输入字段元素,我们可以通过 .files
属性访问用户选择的文件列表。因为文件输入字段允许用户一次选择多个文件,这是一个文件列表。在这里,我们使用 [0]
来获取列表中的第一个文件。因此,$("#my_file")[0].files[0]
返回用户选择的第一个文件。
2、views
from django.shortcuts import render # Create your views here. def index(request): # print(request.body) # b'{"a1":1,"a2":2}' # json_str = json.loads(request.body) # json.loads 能够自动进行二进制解码,然后再反序列化 # print(json_str.get('a1')) if request.method == 'POST': print(request.POST.get('username')) # <QueryDict: {'username': ['DSAD'], 'password': ['DSADAS']}> print(request.FILES.get('myfile')) # <MultiValueDict: {'myfile': [<InMemoryUploadedFile: 462_001_afm_3600_5400.jpg (image/jpeg)>]}> file_obj = request.FILES.get('myfile') with open(file_obj.name, 'wb') as f: for line in file_obj: f.write(line) return render(request, 'index.html')
四、
1、
引入static文件
<script src="/static/layer/layer.js"></script>
引用效果
2、html
{% extends 'home.html' %} {% block content %} <h1 class="text-center">图书列表展示</h1> <a href="/book_add/" class="btn btn-info">添加图书</a> <table class="table table-striped table-hover"> <thead> <tr> <th>标题</th> <th>价格</th> <th>出版日期</th> <th>出版社</th> <th>作者</th> <th>操作</th> </tr> </thead> <tbody> {% for foo in book_queryset %} <tr class="tr_{{ foo.pk }}"> <td>{{ foo.title }}</td> <td>{{ foo.price }}</td> <td>{{ foo.publish_date|date:'Y-m-d' }}</td> <td>{{ foo.publish.name }}</td> {#书查出版社,正向查询,外键字段跳表#} <td> {% for author in foo.authors.all %} {% if forloop.last %} {{ author.name }} {% else %} {{ author.name }} | {% endif %} {% endfor %} </td> <td> {# <a href="/book/edit/{{ foo.pk }}" class="btn btn-success">修改</a>#} <a href="/book_edit/?id={{ foo.pk }}" class="btn btn-success">修改</a> <a href="#" class="del btn btn-danger" delete_id="{{ foo.pk }}">删除</a> {#这里不能使用id标签,因为在for循环中,id不能重复 自定义一个id,a标签自动跳转也相当于有二次提交#} </td> </tr> {% endfor %} </tbody> </table> {% endblock %} {% block js %} <script> $(".del").click(function () { // 删除的逻辑:当我们点击删除按钮的时候,应该获取点击行的id值,然后,把这个id传到后端,后端接收这个id值 // 做删除逻辑 var id = $(this).attr('delete_id'); {#这里的this代表的是$(".btn")对象#} var _this = $(this); // 紧接着要发送ajax请求,最好做一个二次确认 layer.confirm('你确定要删除这条数据吗?', { btn: ['确定'] //按钮 }, function () { // 发送ajax请求 $.ajax({ url: '/book_del/', // {# 把请求提交到del视图函数中去#} type: 'post', data: {id: id}, success: function (res) { if (res.code == 200) { {#layer.msg(res.msg, {icon:2}, function () {#} {# location.reload();} {# ajax不会自动刷新页面 #} layer.msg(res.msg); {# 接收后端返回的信息 #} _this.parent().parent().remove(); {# this 指的是function (res) _this引用变量 #} {#$(".tr_" + id).remove(); 删除dom的tr行来实现不展示#} } } }); }); }) </script> {% endblock %}
3、views
def book_del(request): del_id = request.POST.get('id') # 这个id是 ajx传的 id = $(this).attr('delete_id'); print(del_id) models.Book.objects.filter(pk=del_id).delete() # return redirect('/authors_list/') ajax发过来的数据,不需要页面跳转 return JsonResponse({'code': 200, 'msg': '删除成功!'}) # 如果需要给前端返回数据+'data':{}
4、效果
五、Ajax 实操
简易图书管理系统,前端通过Ajax传数据到后端
html
{% extends 'home.html' %} {% block content %} <h1 class="text-center">修改作者</h1> <div class="container"> <div class="row"> <div class="form-group"> <input type="hidden" id="hidden_id" value="{{ author_obj.pk }}" name="hidden_id"> <div class="form-group"> 作者名:<input type="text" id="name" class="form-control" name="name" value="{{ author_obj.name }}"> </div> </div> <div class="form-group"> 年龄:<input type="text" id="age" class="form-control" name="age" value="{{ author_obj.age }}"> </div> <div class="form-group"> phone:<input type="text" id="phone" class="form-control" name="phone" value="{{ author_obj.author.phone }}"> </div> <div class="form-group"> addr:<input type="text" id="addr" class="form-control" name="addr" value="{{ author_obj.author.addr }}"> </div> <div class="form-group"> <input type="button" id="submitButton" class="btn btn-success btn-block" value="Submit"> </div> <script> $("#submitButton").click(function () { let id = $("#hidden_id").val(); let name = $("#name").val(); let age = $("#age").val(); let phone = $("#phone").val(); let addr = $("#addr").val(); console.log(id) console.log(name) $.ajax({ url: '/authors_edit/', type: 'post', data: {'id':id,'name': name, 'age': age, 'phone': phone, 'addr': addr}, success: function (res) { // 这里可以添加一些成功后的处理逻辑 alert(res.msg); window.location.href=res.url; }, error: function (err) { // 这里可以添加一些错误处理逻辑 alert("提交失败,请重试"); } }) }) </script> </div> </div> {% endblock %}
views
# 修改作者 def authors_edit(request): author_edit_id = request.GET.get('id') # 先获取GET传参的id author_obj = models.Author.objects.filter(pk=author_edit_id).first() # 获取一个publish_obj对象 author_detail_obj = models.Author.objects.filter(pk=author_edit_id).first() # 获取一个publish_obj对象 if request.method == 'POST': new_id = request.POST.get('id') new_name = request.POST.get('name') new_age = request.POST.get('age') new_phone = request.POST.get('phone') new_addr = request.POST.get('addr') # 写入数据库 models.Author.objects.filter(pk=new_id).update(name=new_name, age=new_age) models.Authordetail.objects.filter(author__pk=author_edit_id).update(phone=new_phone, addr=new_addr) res = {'url': '/authors_list/', 'code': 200, 'msg': '后端拿到数据!', 'data': {'username': new_name}} return JsonResponse(res) return render(request, 'authors_edit.html', locals())