1.Ajax简介
AJAX 不是新的编程语言,而是一种使用现有标准的新方法。
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
特点:
异步请求,局部刷新
2.局部刷新
如果是from表单提交之后,如果验证失败会自动刷新页面
使用Ajax能保证只刷新局部
示例:
url
from app01 import views urlpatterns = [ path('admin/', admin.site.urls), path('login/', views.login,name='login'), path('home/', views.home,name='home'), ]
views
from django.shortcuts import render,HttpResponse,redirect # Create your views here. def login(request): if request.method == 'GET': return render(request,'login.html') else: uname = request.POST.get('username') pwd = request.POST.get('password') if uname == 'zbb' and pwd == '123': return HttpResponse('1') else: return HttpResponse('0') def home(request): return render(request,'home.html')
login.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 用户名: <input type="text" id="username"> 密码: <input type="password" id="password"> <button id="sub">提交</button> <span class="error"></span> </body> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <script> $('#sub').click(function () { var uname = $('#username').val(); var pwd = $('#password').val(); $.ajax({ url:'{% url "login" %}', type:'post', data:{username:uname,password:pwd}, success:function (res) { if (res === '1'){ location.href = '/home/'; }else{ $('.error').text('用户名密码错误!'); } } }) }) </script> </html>
home.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>登陆成功</h1> </body> </html>
3.CSRF
详述CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。攻击者通过HTTP请求江数据传送到服务器,从而盗取回话的cookie。盗取回话cookie之后,攻击者不仅可以获取用户的信息,还可以修改该cookie关联的账户信息。
Django默认会禁止未标识 post请求
login.html
4.from请求设置
中加入 {% csrf_token %}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post"> {% csrf_token %} 用户名: <input type="text" id="username"> 密码: <input type="password" id="password"> <input type="submit"> </form> <span class="error"></span> </body> </html>
5.Ajax请求设置
第一种方法
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 用户名: <input type="text" id="username"> 密码: <input type="password" id="password"> <button id="sub">提交</button> <span class="error"></span> </body> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <script> $('#sub').click(function () { var uname = $('#username').val(); var pwd = $('#password').val(); var csrf = '{{ csrf_token }}'; //加在这里 $.ajax({ url:'{% url "login" %}', type:'post', data:{username:uname,password:pwd,csrfmiddlewaretoken:csrf},//发送出 success:function (res) { if (res === '1'){ location.href = '/home/'; // http://127.0.0.1:8000/home/ }else{ $('.error').text('用户名密码错误!'); } } }) }) </script> </html>
第二种方法
需要引入一个jquery.cookie.js插件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 用户名: <input type="text" id="username"> 密码: <input type="password" id="password"> <button id="sub">提交</button> <span class="error"></span> </body> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script> <script> $('#sub').click(function () { var uname = $('#username').val(); var pwd = $('#password').val(); $.ajax({ url:'{% url "login" %}', type:'post', data:{username:uname,password:pwd}, headers:{ "X-CSRFToken":$.cookie('csrftoken'), }, //其实在ajax里面还有一个参数是headers,自定制请求头,可以将csrf_token加在这里,我们发contenttype类型数据的时候,csrf_token就可以这样加 success:function (res) { if (res === '1'){ location.href = '/home/'; }else{ $('.error').text('用户名密码错误!'); } } }) }) </script> </html>
6.网络请求安全解决
常见的网络请求安全解决方法
Cookies Hashing:每一个表单请求中都加入随机的Cookie,由于网站中存在XSS漏洞而被偷窃的危险。 HTTP refer:可以对服务器获得的请求来路进行欺骗以使得他们看起来合法,这种方法不能够有效防止攻击。 验证码:用户提交的每一个表单中使用一个随机验证码,让用户在文本框中填写图片上的随机字符串,并且在提交表单后对其进行检测。 令牌Token:一次性令牌在完成他们的工作后将被销毁,比较安全。
7.文件上传
请求头ContentType
ContentType指的是请求体的编码类型,常见的类型共有3种:
1 application/x-www-form-urlencoded
这应该是最常见的 POST 提交数据的方式了。浏览器的原生 <form> 表单,如果不设置 enctype 属性,那么最终就会以 默认格式application/x-www-form-urlencoded 方式提交数据,ajax默认也是这个。请求类似于下面这样(无关的请求头在本文中都省略掉了): POST http://www.example.com HTTP/1.1 Content-Type: application/x-www-form-urlencoded;charset=utf-8 user=yuan&age=22 #这就是上面这种contenttype规定的数据格式,后端对应这个格式来解析获取数据,不管是get方法还是post方法,都是这样拼接数据,大家公认的一种数据格式,但是如果你contenttype指定的是urlencoded类型,但是post请求体里面的数据是下面那种json的格式,那么就出错了,服务端没法解开数据。
2.multipart/form-data
这又是一个常见的 POST 数据提交的方式。我们使用表单上传文件时,必须让 <form> 表单的 enctype 等于 multipart/form-data,form表单不支持发json类型的contenttype格式的数据,而ajax什么格式都可以发,也是ajax应用广泛的一个原因
3.application/json
application/json 这个 Content-Type 作为响应头大家肯定不陌生。实际上,现在越来越多的人把它作为请求头,用来告诉服务端消息主体是序列化后的 JSON 字符串。由于 JSON 规范的流行,除了低版本 IE 之外的各大浏览器都原生支持 JSON.stringify,服务端语言也都有处理 JSON 的函数,使用 JSON 不会遇上什么麻烦。
form表单文件上传
url
path('upload/', views.upload,name='upload'),
views
def upload(request): if request.method == "GET": return render(request,'upload.html') else: print(request.POST) print(request.FILES) uname = request.POST.get("username") pwd = request.POST.get('password') file_obj = request.FILES.get('file') print(file_obj.name) with open(file_obj.name,'wb') as f: # for i in file_obj: # f.write(i) #文件太大只有一行怎么办? for chunk in file_obj.chunks(): #默认一次返回大小为经测试为65536B,也就是64KB,最大为2.5M,是一个生成器 f.write(chunk) return HttpResponse("ok")
upload.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="" method="post" enctype="multipart/form-data"> {# 告诉浏览器不要一起发送,要一段一段的发送,指定:ContentType ..指的是请求体的编码类型#} {% csrf_token %} 用户名: <input type="text" name="username"> 密码: <input type="password" name="password"> 头像: <input type="file" name="file"> <input type="submit"> </form> </body> </html>
Ajax文件上传
upload.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 用户名: <input type="text" name="username"> 密码: <input type="password" name="password"> 头像: <input type="file" name="file" multiple> {# multiple 的意思是可以上传多个#} <button id ='sub'>提交</button> <span class='error'></span> </body> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script> <script> $('#sub').click(function () { var formdata = new FormData(); var uname = $('#username').val(); var pwd = $('#password').val(); var file_obj = $('[type=file]')[0].files[0]; formdata.append('username',uname); formdata.append('password',pwd); formdata.append('file',file_obj); $.ajax({ url:'{% url "upload" %}', type:'post', data:formdata, processData:false, contentType:false, //固定语法 不得对数据加工,直接发送原生数据 headers:{ "X-CSRFToken":$.cookie('csrftoken'), }, success:function (res) { $('.error').text('完成'); } }) }) </script> </html>
8.json数据交互
json数据类型和python数据类型的对比
JsonResponse对象
JsonResponse是HttpResponse的子类,专门用来生成JSON编码的响应。
from django.http import JsonResponse response = JsonResponse({'foo': 'bar'}) print(response.content) b'{"foo": "bar"}'
class JsonResponse
(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None,**kwargs)
这个类是HttpRespon的子类,它主要和父类的区别在于:
1.它的默认Content-Type 被设置为: application/json
2.第一个参数,data应该是一个字典类型,当 safe 这个参数被设置为:False ,那data可以填入任何能被转换为JSON格式的对象,比如list, tuple, set。 默认的safe 参数是 True. 如果你传入的data数据类型不是字典类型,那么它就会抛出 TypeError的异常。
3.json_dumps_params参数是一个字典,它将调用json.dumps()方法并将字典中的参数传入给该方法。
#如果这样返回,ajax还需要进行json解析 #views.py return HttpResponse(json.dumps({"msg":"ok!"})) #index.html var data=json.parse(data) console.log(data.msg);
使用HttpResponse对象来响应数据的时候,还可以通过content_type指定格式:
return HttpResponse(json.dumps(data),content_type="application/json")
前端调试窗口就可以看到这个类型
如果不写这个参数是这个类型:长得像json格式的字符串,当然也可以转换成json的
看下面这种,JsonResponse默认就是content_type="application/json"。
#如果这样返回,两边都不需要进行json的序列化与反序列化,ajax接受的直接是一个对象 #views.py from django.http import JsonResponse return JsonResponse({"msg":"ok!"}) #index.html console.log(data.msg);
urls
path('jsontest/', views.jsontest,name='jsontest'),
代码 views
from django.http import JsonResponse import json def jsontest(request): """ 状态码; 1000 : 登录成功 1001 : 登录失败 :param request: :return: """ if request.method == 'GET': return render(request,'jsontest.html') else: username = request.POST.get('username') pwd = request.POST.get('password') ret_data = {'status':None,'msg':None} print('>>>>>',request.POST) #<QueryDict: {'{"username":"123","password":"123"}'> if username == 'zbb' and pwd == '123': ret_data['status'] = 1000 # 状态码 ret_data['msg'] = '登录成功' else: ret_data['status'] = 1001 # 状态码 ret_data['msg'] = '登录失败' # ret_data_json = json.dumps(ret_data,ensure_ascii=False) # return HttpResponse(ret_data_json,content_type='application/json') #ret_data = ['aa',22,'bb'] /如果是数组 return JsonResponse(ret_data) #safe =Flaser
jsontest.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 用户名: <input type="text" id="username"> 密码: <input type="password" id="password"> <button id="sub">提交</button> <span class="error"></span> </body> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <script src="https://cdn.bootcss.com/jquery-cookie/1.4.1/jquery.cookie.js"></script> <script> $('#sub').click(function () { var uname = $('#username').val(); var pwd = $('#password').val(); $.ajax({ url:'{% url "jsontest" %}', type:'post', data:{username:uname,password:pwd}, headers:{ "X-CSRFToken":$.cookie('csrftoken'), }, success:function (res) { {#console.log(res,typeof res); // statusmsg {"status": 1001, "msg": "登录失败"}#} console.log(res,typeof res); //直接就是反序列化之后的了 if (res.status === 1000){ location.href = '/home/'; }else{ $('.error').text(res.msg); } } }) }) </script> </html>
9.补充一个SweetAlert插件
下载地址 百度jq2
https://github.com/lipis/bootstrap-sweetalert
url
path('chajian/', views.chajian)
views
def chajian(request): return render(request,'chajian.html')
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-theme.min.css' %}"> <link rel="stylesheet" href="{% static 'bootstrap-sweetalert-master/dist/sweetalert.css' %}"> </head> <body> <div> <button class="btn btn-danger">删除</button> </div> </body> <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script> <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script> <script src="{% static 'bootstrap-sweetalert-master/dist/sweetalert.js' %}"></script> <script> $(".btn-danger").on("click", function () { swal({ title: "你确定要删除吗?", text: "删除可就找不回来了哦!", type: "warning", showCancelButton: true, confirmButtonClass: "btn-danger", confirmButtonText: "我已经下定决心", cancelButtonText: "容我三思", closeOnConfirm: false }, function () { var deleteId = $(this).parent().parent().attr("data_id"); $.ajax({ url: "/delete_book/", type: "post", data: {"id": deleteId}, success: function (data) { console.log(data,typeof data); if (data === '1') { swal("删除成功!", "你可以准备跑路了!", "success"); } else { swal("删除失败", "你可以再尝试一下!", "error") } } }) }); }) </script> </html>