第七篇:Ajax功能模块

Ajax

Ajax并不是一门新的语言,它其实就是基于js写的一个功能模块。使用JavaScript语言与服务器进行异步交互,传输数据为XML。

AJAX最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。

  • 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求
  • 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求

AJAX常见应用情景:

用于注册的时候用户名的查重,当文本框发生了输入变化时,使用AJAX技术向服务器发送一个请求,然后服务器会把查询的结果响应给浏览器,最后再把后端返回的结果展示出来。通过异步回调机制callback()拿到任务的结果。

  • 整个过程页面没有刷新,只是刷新页面中的局部位置
  • 当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应

优点:

  • 局部刷新
  • 异步请求

由于原生js书写ajax较为繁琐,所以我们直接使用jQuery封装好的ajax模块操作,因此需要下载jQuery。

Ajax基本语法结构

// ajax基本语法$.ajax({ // 1.指定朝那个后端提交数据,默认不写是朝当前页面的后端提交 url:'', // 控制数据的提交路径 有三种写法 跟form表单的action属性一致 // 2.指定当前请求方式 type:'post', // 3.提交的数据 data:{'i1':$('#i1').val(),'i2':$('#i2').val()}, // 4.ajax是异步提交 所以需要给一个回调函数来处理返回的结果 success:function (data) { // data就是异步提交的返回结果 // 将异步回调的结果通过DOM操作渲染到第三个input框中 $('#i3').val(data) }})

第一个AJAX案例

案例:页面上有三个input框 一个按钮
用户在前两个框中输入数字 点击按钮保证页面不刷新的情况下将数据发到后端做计算
将计算好的结果再发给前端展示到第三个input框中

# urls.pyurl(r'^index/', views.index) # views.pydef index(request): if request.method == 'POST': i1 = request.POST.get('i1') i2 = request.POST.get('i2') i3 = int(i1) + int(i2) print(i3) return HttpResponse(i3) return render(request, 'index.html') # index.html<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>index</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script></head><body><input type="text" id="i1"> + <input type="text" id="i2"> = <input type="text" id="i3"><button id="d1">按钮</button> <script> $('#d1').click(function () { $.ajax({ url: '', type: 'post', data: {'i1': $('#i1').val(), 'i2': $('#i2').val()}, success: function (data) { $('#i3').val(data) } }) })</script></body></html>

Content-Type前后端传输数据编码格式

urlencoded:

数据格式 username=jason&password=123

是form表单和ajax默认的编码格式

django后端针对符合该格式的数据都会自动解析并放到request.POST中

post和get使用URLencode转码,post格式和get格式的区别在于,get把转换,拼接完的字符串用‘?’直接跟在url后面,所以请求体中没有数据;而post把转换、拼接后的字符串放在了请求体里,不会在浏览器的地址栏显示,因为更安全一些。

formdata:

既可以发送文件也可以继续发送普通键值对

django后端会将该编码格式中符合username=jason&password=123格式数据还是放到request.POST中

而针对文件数据则会解析放到request.FILES

application/json:

传输数据格式要与编码格式保持一致

form表单:

默认是urlencoded编码格式传输数据

urlencoded数据格式

username=jason&password=123

django后端针对该格式的数据,会自动解析并帮你打包到request.POST中

formdata数据格式

django后端针对符合urlencoded编码格式数据还是统一解析到request.POST中

而针对formdata文件数据就会自动解析放到request.FILES中

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script></head><body>{#<form action="" method="post" enctype="multipart/form-data">#}{# <input type="text" name="username">#}{# <input type="text" name="password">#}{# <input type="file" name="myfile">#}{# <input type="submit">#}{#</form>#}{##}{#<button id="d1">点击发送ajax请求</button>#}{##}{##}{#<button id="d2">ajax发送json格式数据</button>#}<input type="file" name="myfile" id="i1"><button id="d3">ajax发送文件数据</button> <script> $('#d1').click(function () { $.ajax({ url:'', type:'post', data:{'username':'jason','password':123}, success:function (data) { alert(data) } }) })</script></body></html>

Ajax发送json格式数据

ajax默认的也是urlencoded编码格式

前后端数据交互,编码格式要与数据格式一定要一致

application/json

django后端针对json格式数据并不会做任何的处理,而是直接放到request.body中

需要自己手动处理该数据

 // 发json格式 $('#d2').on('click',function () { $.ajax({ url:'', type:'post', // 修改content-Type参数 contentType:'application/json', data:JSON.stringify({'username':'jason','password':123}), // 将数据序列化成json格式字符串 success:function (data) { alert(data) } }) })
# views.py def ab_ct(request): if request.method == 'POST': print(request.body) # jason.loads可以直接反序列化符合json格式的二进制数据,不需要先解码后再进行

Ajax发送文件数据

内置对象FormData

即发普通键值对也发文件

 // ajax发送文件数据 需要借助于内置对象 $('#d3').click(function () { // 1 需要先生成一个内置对象 var myFormData = new FormData(); // 2 传普通键值对 当普通键值对较多的时候 我们可以利用for循环来添加 myFormData.append('username','jason'); myFormData.append('password',123); // 3 传文件 myFormData.append('myfile',$('#i1')[0].files[0]); // 获取input框内部用户上传的文件对象 // 发送ajax请求 $.ajax({ url:'', type:'post', data:myFormData, // 发送formdata对象需要指定两个关键性的参数 processData:false, // 让浏览器不要对你的数据进行任何的操作 contentType:false, // 不要使用任何编码格式 对象formdata自带编码格式并且django能够识别该对象 success:function (data) { alert(data) } }) })
# views.py def ab_ct(request): if request.method == 'POST': print(request.FILES)

django内置的序列化功能

前后端数据交互一般情况下都是一个大字典

接口文档,表名该大字典内都有哪些键值对:postman

from app01 import modelsfrom django.core import serializersdef ab_se(request): user_queryset = models.Userinfo.objects.all() # user_list = [] # for user_obj in user_queryset: # user_list.append({ # 'username':user_obj.username, # 'password':user_obj.password, # 'gender':user_obj.get_gender_display(), # }) # res = jso n.dumps(user_list) res = serializers.serialize('json',user_queryset) return HttpResponse(res) 

Ajax结合sweetalert实现删除二次确认

urls.py

url(r'^show_user/',views.show_user)

views.py

from django.http import JsonResponseimport timedef show_user(request): """ 前后端如果是通过ajax进行交互 那么交互的媒介一般情况下都是一个字典 :param request: :return: """ if request.method == 'POST': time.sleep(3) back_dic = {"code":1000,'msg':''} delete_id = request.POST.get('delete_id') models.Userinfo.objects.filter(pk=delete_id).delete() back_dic['msg'] = '删除成功,准备跑路!!!' return JsonResponse(back_dic) user_queryset = models.Userinfo.objects.all() return render(request,'show_user.html',locals())

html:

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> {% load static %} <link rel="stylesheet" href="{% static 'dist/sweetalert.css' %}"> <script src="{% static 'dist/sweetalert.min.js' %}"></script> <style> div.sweet-alert h2 { padding-top: 10px; } </style></head><body><div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <h2 class="text-center">数据展示</h2> <table class="table-hover table table-striped"> <thead> <tr> <th>主键</th> <th>用户名</th> <th>密码</th> <th>性别</th> <th>操作</th> </tr> </thead> <tbody> {% for user_obj in user_queryset %} <tr> <td>{{ user_obj.pk }}</td> <td>{{ user_obj.username }}</td> <td>{{ user_obj.password }}</td> <td>{{ user_obj.get_gender_display }}</td> <td> <a href="#" class="btn btn-primary btn-xs">编辑</a> <a href="#" class="btn btn-danger btn-xs cancel" data_id="{{ user_obj.pk }}">删除</a> </td> </tr> {% endfor %} </tbody> </table> </div> </div></div> <script> $('.cancel').click(function () { var $aEle = $(this); swal({ title: "你确定要删吗?", text: "你如果删了,你可要准备跑路啊!", type: "warning", showCancelButton: true, confirmButtonClass: "btn-danger", confirmButtonText: "是的,老子就要删!", cancelButtonText: "惹不起惹不起!", closeOnConfirm: false, closeOnCancel: false, showLoaderOnConfirm: true }, function (isConfirm) { if (isConfirm) { // 发送ajax请求 $.ajax({ url:'', type:'post', data:{'delete_id':$aEle.attr("data_id")}, success:function (data) { // 回调函数会自动将二进制的json格式数据 解码并反序列成js中的数据类型 if (data.code == 1000){ swal("删了!", "你准备跑路吧!", "success"); // 方式1 {#window.location.reload()#} // 方式2 DOM操作动态修改 $aEle.parent().parent().remove() // 将标签直接移除 }else{ swal('发生了未知的错误', "error"); } } }); } else { swal("怂笔", "你成功的刷新我对你的认知", "error"); } }); })</script></body></html>

批量插入数据

# views.pydef ab_bc(request): # 先插入1000条件数据 # for i in range(1,1001): # models.Book.objects.create(title='第%s本书'%i) book_list = [] for i in range(1,10001): book_list.append(models.Book(title='新的%s书'%i)) models.Book.objects.bulk_create(book_list) # 批量插入数据的方式 book_queryset = models.Book.objects.all() return render(request,'ab_bc.html',locals())
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script> <link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"> <script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script> </head><body>{% for book_obj in page_queryset %} <p>{{ book_obj.title }}</p>{% endfor %}</body></html>

自定义分页器

后端:

# 1 现生成一个自定义分页器类对象page_obj = Pagination(current_page=request.GET.get('page', 1), all_count=book_queryset.count(), pager_count=9)# 2 针对真实的queryset数据进行切片操作queryset_data = queryset[page_obj.start:page_obj.end]# 3.将切片之后的数据传递到前端页面return render(request,'list.html',{"data":queryset_data})# 或者直接返回所有的变量return render(request,'ab_bc.html',locals())

前端:

{% for book_obj in page_queryset %} <p>{{ book_obj.title }}</p>{% endfor %}{{ page_obj.page_html|safe }}

相关文章