Ajax : 异步请求,不会刷新页面,页面上用户之前输入的数据都不会丢失。
简单请求案例:
views页面
from django.shortcuts import render,HttpResponse,redirect from django.urls import reverse def login(request): if request.method == "POST": if request.POST.get("uname") == "root": return HttpResponse("ok") return HttpResponse("error") return render(request, "login.html") def home(request): return render(request,"home.html")
HTML页面
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <label> 用户名: <input type="text" name="username" id="username"> </label> <label> 密码: <input type="password" name="password" id="password"> </label> <button id="btn">提交</button> <span style="color: red;font-size: 12px" id="err"></span> </div> </body> <script src="{% static 'js/jquery.js' %}"></script> <script> $('#btn').click(function (){ var name = $('#username').val(); var pwd = $('#password').val(); console.log(name,pwd) $.ajax({ url: {% url 'login' %}', type: 'post', data: {uname:name,upwd:pwd}, success: function (res) { console.log(res, typeof res) if(res==="ok"){ location.href = '{% url 'home' %}'; } else{$('#err').text("用户名或者密码错误") } } }) }) </script> </html>
注意点:
$.ajax({ //
url:'/login_ajax/', //写路径时,如果后台使用的是django框架,那么url路径的后面的斜杠要加上,如果想不加上斜杠,
那么需要在django的settings配置文件中加上 APPEND_SLASH = False,并且后台的urls.py文件中的路径要和ajax请求路径对应好,
该有斜杠写斜杠,不需要斜杠的,去掉斜杠
type:'post',
...
}),
在js代码中使用url别名反向解析来写路径:
$.ajax({ //
url:'{% url "login_ajax" %}',
type:'post',
...
}),
但是,要注意一点,当这段js代码是写到某个js文件中,然后hmtl文件通过script标签的src属性来引入时,
{% url "login_ajax" %}语法就不能被模板渲染了,也就是失效了
响应字典数据类型
方式一: 手动利用json序列化和反序列化
views页面
from django.shortcuts import render,HttpResponse,redirect from django.urls import reverse from django.http import JsonResponse def login(request): if request.method == "POST": if request.POST.get("uname") == "root": return HttpResponse("ok") return HttpResponse("error") return render(request, "login.html") def home(request): return render(request,"home.html") def data(request): import json dic = {"summer":["夏日惊喜","西瓜","哈密瓜","凉面"]} dic_str = json.dumps(dic,ensure_ascii=False) return HttpResponse(dic_str)
HTML页面
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>这是home页面</h1> <button id="btn_home">点击有惊喜</button> <ul> </ul> </body> <script src="{% static 'js/jquery.js' %}"></script> <script> $('#btn_home').click(function () { $.ajax({ url: '{% url "data" %}', type: 'get', success: function (res) { console.log(res, typeof res) // 夏天 string 用HttpResponce传递字典数据, 只能取到字典的键 // 引入json模块后得到字符串形式的字典: {"summer": ["西瓜", "哈密瓜", "凉面"]} string var dic_res = JSON.parse(res) console.log(dic_res,typeof dic_res) var ret = dic_res.summer // 将列表中的内容放到页面中 for (var i=0;i<ret.length;i++){ var content = ret[i]; var liEle = document.createElement('li'); liEle.innerText = content $('ul').append(liEle); } } }) }) </script> </html>
# 第一种方式,直接通过HttpResponse回复字典数据,那么ajax接受到数据之后,需要自行反序列化
# data_list_str = json.dumps(data_list, ensure_ascii=False)
# 直接使用HttpResponse回复字典类型数据,那么会将字典里面元素的键都拼接成一个字符串来响应,所以不是我们想要的结果,所以我们先将字典类型数据,转换成json字符串,在通过HttpResponse来进行响应
方式二: 手动加响应头键值对 ['content-type'] = 'application/json'
# data函数改写 def data(request): import json dic = {"summer":["夏日惊喜","西瓜","哈密瓜","凉面"]} dic_str = json.dumps(dic,ensure_ascii=False) ret = HttpResponse(dic_str) ret['content-type'] = 'application/json' return ret # HTML接收和显示数据修改 success: function (res) { console.log(res, typeof res) // 夏天 string 用HttpResponce传递字典数据, 只能取到字典的键 // 引入json模块后得到字符串形式的字典: {"summer": ["西瓜", "哈密瓜", "凉面"]} string {#var dic_res = JSON.parse(res)#} {#console.log(dic_res,typeof dic_res)#} var ret = res.summer // 将列表中的内容放到页面中 for (var i=0;i<ret.length;i++){ var content = ret[i]; var liEle = document.createElement('li'); liEle.innerText = content $('ul').append(liEle);
#第二种方式:通过HttpResponse回复字典数据,回复之前,加上一个响应头键值对,如下,那么ajax收到这个响应数据的时候,
会查看这个响应头,发现content-type这个响应头的值为application/json,那么会自动对响应数据进行反序列化,不需要我们自己手动反序列化了
方式三: 引入JsonHttpResponce
# data部分 from django.http import JsonResponse def data(request): import json dic = {"summer":["夏日惊喜","西瓜","哈密瓜","凉面"]} # dic_str = json.dumps(dic,ensure_ascii=False) # ret = HttpResponse(dic_str) # ret['content-type'] = 'application/json' return JsonResponse(dic)
#JsonResponse:1 序列化数据 2 加上['content-type'] = 'application/json'这个响应头键值对
注意:
lst = ["夏日惊喜","西瓜","哈密瓜","凉面"] #当使用JsonResponse回复非字典类型数据时,需要将safe参数的值改为False, 不然会报错 return JsonResponse(lst, safe=False)
局部更新数据案例:
views页面
def sub(request): if request.method == "GET": return render(request,"sub.html") else: import json print(request.body) data = request.body.decode() print(data) data = json.loads(data) print(data) a = int(data["a"]) b = int(data["b"]) ret = a+b print(ret) return HttpResponse(ret)
HTML页面
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <label> a: <input type="text" name="a" id="aid"> </label> <label> b: <input type="text" name="b" id="bid"> </label> <button id="btn_sub">查询</button> <br> a+b= <span id="sp" style="color: burlywood"></span> </body> <script src="{% static 'js/jquery.js' %}"></script> <script> $('#btn_sub').click(function () { var a = $('#aid').val(); var b = $('#bid').val(); $.ajax({ url: '{% url 'sub' %}', type: 'post', headers: { 'Content-Type':'application/json', }, data: JSON.stringify({a:a,b:b}), success: function (res) { {#alert(res);#} $('#sp').text(res) } }) }) </script> </html>
请求头消息格式分析
请求消息格式和请求方法没有关系, 和请求头键值对中的这一组键值对有关系
file说明 <!-- enctype="multipart/form-data"这个参数就是将本次请求的消息格式,也就是那个content-type的值改为multipart/form-data,
那么本次http请求,会将文件数据片段发送 -->
Content-Type: application/x-www-form-urlencoded; //浏览器发送数据ajax或者form表单,默认的格式都是它 它表示请求携带的数据格式,application/x-www-form-urlencoded对应的数据格式是:a=1&b=2
'''
socket 接收到我们请求数据,会分析一下Content-Type: application/x-www-form-urlencoded;这个请求头
# 叫做解析器
if Content-Type == 'application/x-www-form-urlencoded':
data = 'a=1&b=2'
l1 = data.split('&') [a=1,b=2]
for i in l1:
k,v = i.split('=')
if 请求方法 == 'GET':
request.GET[k] = v
elif Content-Type == 'multipart-formdata':
request.FILES
#django没有内置对appcation/json的消息格式的解析器,所以如果请求数据是json类型,那么我们需要自行解析
'''
ajax结合sweetalert删除数据案例:
views页面
class Del_book(View): def get(self,request,pk): try: models.Book.objects.get(id=pk).delete() except: return HttpResponse('没有这本书的信息',status=404) # return HttpResponse('error') #默认响应的状态码都是200 return HttpResponse('ok')
HTML页面
{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}"> <link rel="stylesheet" href="{% static 'bootstrap-sweetalert-master/dist/sweetalert.css' %}"> </head> <body> <div class="container"> <h1>书籍展示</h1> <div class="row"> <div class="clo-md-8 col-md-offset-2"> <a href="{% url 'add_book' %}" class="btn btn-primary" style="margin-bottom: 10px">添加书籍</a> <table class="table table-bordered table-hover table-striped"> <thead> <tr> <th>编号</th> <th>书名</th> <th>价格</th> <th>出版日期</th> <th>出版社</th> <th>作者</th> <th>操作</th> </tr> </thead> <tbody> {% for each_book in book_obj %} <tr> <td>{{ forloop.counter }}</td> <td>{{ each_book.title }}</td> <td>{{ each_book.price }}</td> <td>{{ each_book.pub_date|date:'Y-m-d' }}</td> <td>{{ each_book.pud.name }}</td> <td>{{ each_book.author_name }}</td> <td> <a href="{% url 'update_book' each_book.id %}" class="btn btn-warning">编辑</a> <span class="id_num hidden">{{ each_book.id }}</span> <button class="btn btn-danger">删除</button> </td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </body> <script src="{% static 'js/jquery.js' %}"></script> <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script> <script src="{% static 'bootstrap-sweetalert-master/dist/sweetalert.min.js' %}"></script> <script> $(".btn-danger").on("click", function () { var delete_id = $(this).prev().text() var ths = $(this) //因为下面的函数中this指向的不是我们的标签按钮,所以通过一个变量来保存一下这个$(this),方便后面使用 swal({ title: "are you sure?", text: "要谨慎!", type: "warning", showCancelButton: true, confirmButtonClass: "btn-danger", confirmButtonText: "确定删除", cancelButtonText: "容我三思", closeOnConfirm: false }, (function () { $.ajax({ url: '/del_book/' + delete_id + '/', type: 'get', success: function (res) { //当状态码为2xx或者3xx时才认为是请求正常成功了,会触发success对应的函数。但是当状态为4xx、5xx的时候,ajax认为此次请求是失败的会触发error属性对应的函数 if (res === "ok") { swal("删除成功!", "success"); //关闭弹框 ths.parents('tr').remove() //删除页面上对应的数据 } }, error: function (res) { if (res.status === 404) { console.log(res.responseText) //res.responseText是后台响应回来的错误信息 swal("删除失败!", res.responseText, "error") } } }) })); }) </script>
箭头函数:
普通函数:var k = function(参数){return 'kkkk'}; 箭头函数:var k = (参数) =>{return 'kkkk'}; 箭头函数简写: var k = (参数)=>'kkkk'
js函数中this的指向问题
var a = 'xx'; var d1 = { a:'ss', f: () => { //this指向函数调用者 // console.log(this); console.log(this.a); } } d1.f() #调用者是d1对象,所以打印的内容为ss # 函数的单体模式 var a = 'xx'; var d1 = { a:'ss', f(){ console.log(this.a); //结果为:ss }, } d1.f() # 箭头函数,改变this的指向,将this指向上下文的this var a = 'xx'; var d1 = { a:'ss', f:()=>{ console.log(this); // 指向了Window对象 console.log(this.a); //结果为xx f1() }, } d1.f() // var a = 'xx'; var d1 = { a:'ss', f:function(){ console.log(this.a); // ss function f1(){ console.log(this); // 指向了Window对象 console.log(this.a); //结果为xx } f1() }, } d1.f() //箭头函数改变this指向 var a = 'xx'; var d1 = { a:'ss', f:function(){ console.log(this.a); // ss var f1 = ()=>{ console.log(this); // 指向了d1对象 console.log(this.a); //结果为ss } f1() }, } d1.f() //箭头函数改变this指向 var a = 'xx'; var d1 = { a:'ss', f:()=>{ console.log(this.a); // xx var f1 = ()=>{ console.log(this); // 指向了window对象 console.log(this.a); //结果为xx } f1() }, } d1.f()