64 Django -- Ajax
目录
AjaxAjax简介AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”。即使用Javascript语言与服务器进行异步交互,传输的数据为XML(当然,传输的数据不只是XML,现在更多使用json数据)。 ? AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程) AJAX 不需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。 特点:异步请求、局部刷新 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发出第二个请求。 局部刷新:可以局部添加网页内容,如提示:用户名或者密码错误等。 AJAX常见应用情景
Ajax的优缺点https://www.cnblogs.com/SanMaoSpace/archive/2013/06/15/3137180.html 优点:
缺点:
Ajax简单登录认证用form表单登录,提交数据会刷新页面。ajax不会刷新。 login.html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width,initial-scale=1"> <title>Title</title> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email?protected]/dist/css/bootstrap.min.css"> </head> <body> <div style="width: 500px;height:200px;background-color: #4ba7ff;margin-top: 180px; margin-left: 350px;"> <div style="padding-top:50px;"> <div class="form-group"> <label class="col-sm-2 control-label">用户名</label> <div class="col-sm-10"> <input type="text" class="form-control" placeholder="请输入用户名" id="username"> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">密码</label> <div class="col-sm-10"> <input type="password" class="form-control" placeholder="请输入密码" id="password"> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-default" id="sub">登 录</button> <span id="error" style="color: red"></span> </div> </div> </div> </div> </body> <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> <script src="https://cdn.jsdelivr.net/npm/[email?protected]/dist/js/bootstrap.min.js"></script> <script > $('#sub').click(function () { // 绑定点击事件,一点击 登录 会将数据提交给后端,不会刷新页面 var username=$('#username').val(); var password=$('#password').val(); $.ajax({ url:'{% url "login" %}',// type:'post',data:{'user':username,'pwd':password},// data会携带数据提交到url路径 res:是接收后端返回的数据 success:function (res) { if(res === '1'){ // 表示登录成功,跳转到home页面 location.href='{% url "home" %}'} else{ // 登录失败,局部刷新,添加提示 $('#error').text('用户名或密码错误!') } } }) }) </script> </html> 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'^login/',views.login,name='login'),url(r'^home/',views.home,name='home'), views.py from django.shortcuts import render,HttpResponse,redirect def login(request): if request.method=='GET': return render(request,'login.html') else: user = request.POST.get('user') # 获取ajax中data携带的数据 pwd = request.POST.get('pwd') if user == 'yan' and pwd == '123': # 假设用户名与密码 return HttpResponse('1') # 登录成功返回1 else: return HttpResponse('0') # 登录成功返回0 def home(request): return render(request,'home.html') csrf认证CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。攻击者通过HTTP请求将数据传送到服务器,从而盗取回话的cookie。盗取回话cookie之后,攻击者不仅可以获取用户的信息,还可以修改该cookie关联的账户信息。 ? 所以解决csrf攻击的最直接的办法就是生成一个随机的csrftoken值,保存在用户的页面上,每次请求都带着这个值过来完成校验。 token字符串的前32位是salt, 后面是加密后的token, 通过salt能解密出唯一的secret。 form表单设置csrf_token{% csrf_token %} 标签,加上这个标签,模板渲染之后就是一个隐藏的input标签,提交数据时,会随数据一起提交给后端。 <input type="hidden" name=‘csrfmiddlewaretoken’ values=‘dkjdkasiofaad...’> <form action="" method="post"> {% csrf_token %} // form表单里面加上这个标签,模板渲染之后就是input标签 <div style="width: 500px;height:200px;background-color: #4ba7ff;margin-top: 180px; margin-left: 350px;"> <div style="padding-top:50px;"> <div class="form-group"> <label class="col-sm-2 control-label">用户名</label> <div class="col-sm-10"> <input type="text" class="form-control" placeholder="请输入用户名" id="username" name='username'> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">密码</label> <div class="col-sm-10"> <input type="password" class="form-control" placeholder="请输入密码" id="password" name='password'> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <button type="submit" class="btn btn-default" id="sub">登 录</button> <span id="error" style="color: red"></span> </div> </div> </div> </div> </form> Ajax设置csrf认证方式一:通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。 // 在body标签中,增加 {% csrf_token %} 标签 <script > $('#sub').click(function () { var username=$('#username').val(); var password=$('#password').val(); // csrf方式一: var csrf=$('[name=csrfmiddlewaretoken]').val(); // 使用jQuery取出csrfmiddlewaretoken的值, $.ajax({ url:'{% url "login" %}',type:'post','pwd':password,"csrfmiddlewaretoken":csrf},// data会携带数据 success:function (res) { if(res === '1'){ location.href='{% url "home" %}'} else{ console.log(res); $('#error').text('用户名或密码错误!') } } }) }) </script> 方式二:用 {{ csrf_token }} 变量直接获取csrfmiddlewaretoken的值 <script > $('#sub').click(function () { var username=$('#username').val(); var password=$('#password').val(); // csrf方式二: var csrf = '{{ csrf_token }}'; $.ajax({ url:'{% url "login" %}',// data会携带数据 success:function (res) { if(res === '1'){ location.href='{% url "home" %}'} else{ console.log(res); $('#error').text('用户名或密码错误!') } } }) }) </script> 方式三:引入:jquery.cookie.js;下载:http://plugins.jquery.com/cookie/ 通过获取返回的cookie中的字符串 放置在请求头中发送。 ? Ajax里面还有一个参数是headers,自定制请求头,可以将csrf_token加在这里,发contenttype类型数据的时候,csrf_token就可以这样加。 <script > $('#sub').click(function () { var username=$('#username').val(); var password=$('#password').val(); $.ajax({ url:'{% url "login" %}',// data会携带数据 // csrf 方式三: headers:{ "X-CSRFToken":$.cookie('csrftoken'),},// 必须引入jquery.cookie.js success:function (res) { if(res === '1'){ location.href='{% url "home" %}'; {#$('#error').text('登录成功!'); }#} } else{ {#console.log(res);#} $('#error').text('用户名或密码错误!') } } }) }) </script> 注意: 如果使用从cookie中取csrftoken的方式,需要确保cookie存在csrftoken值。 如果你的视图渲染的HTML文件中没有包含 {% csrf_token %},Django可能不会设置CSRFtoken的cookie。 这个时候需要使用ensure_csrf_cookie()装饰器强制设置Cookie。 django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def login(request): pass 文件上传请求头Content-Type服务端告诉浏览器,数据是以什么封装的。否则浏览器不知道怎样解开数据。 1. Content-Type: application/x-www-form-urlencoded;charset=utf-8 # 最常见的 POST 提交数据的方式了。浏览器的原生 <form> 表单,如果不设置 enctype 属性,那么最终就会以 默认格式application/x-www-form-urlencoded 方式提交数据,ajax默认也是这个。 user=yan&pwd=123 #这就是上面这种content-type规定的数据格式,后端对应这个格式来解析获取数据,不管是get方法还是post方法,都是这样拼接数据,大家公认的一种数据格式. 2. Content-Type:multipart/form-data; # form表单设置enctype属性时,post提交数据的方式 3. Content-Type:application/json # 告诉浏览器 服务端消息主体是序列化后的 JSON 字符串。 form表单上传文件在form中加 enctype="multipart/form-data"。form表单不支持发json类型的content-type格式的数据,而ajax什么格式都可以发,也是ajax应用广泛的一个原因。 <form action="" method="post" enctype="multipart/form-data"> {% csrf_token %} 用户名: <input type="text" name="username"> 密码: <input type="password" name="password"> 文件: <input type="file" name="file"> <input type="submit"> </form> views.py from django.conf import settings # 能用全局settings获取一些配置,如路径等 def upload(request): if request.method == 'GET': print(settings.BASE_DIR) #/static/ 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) # 方式二:chunks()默认一次返回大小为65536B,也就是64KB,最大为2.5M的数据,是一个生成器 for chunk in file_obj.chunks(): f.write(chunk) return HttpResponse('ok') 通过js来找文件对象 Ajax的上传文件<script > $('#sub').click(function () { // 创建一个对象 var formdata = new FormData(); var user = $('#username').val(); var pwd = $('#password').val(); var file_obj = $('[type=file]')[0].files[0]; // js获取文件对象 // 封装 formdata.append('username',user); formdata.append('password',pwd); formdata.append('file',file_obj); $.ajax({ url:'{% url "upload" %}',// data:{username:user,password:pwd,csrfmiddlewaretoken:csrf},//data:{username:uname,password:pwd},data:formdata,processData:false,// 必须写,告诉不做任何预处理 contentType:false,// 必须写 headers:{ "X-CSRFToken":$.cookie('csrftoken'),success:function (res) { console.log(res); if (res === '1'){ // $('.error').text('登录成功'); location.href = '/home/'; // http://127.0.0.1:8000/home/ }else{ $('.error').text('用户名密码错误!'); } } }) }) </script> views.py def upload(request): if request.method == 'GET': return render(request,'wb') as f: # 方式一:一行一行读取并写入: # for i in file_obj: # f.write(i) # 方式二:chunks()默认一次返回大小为65536B,也就是64KB,最大为2.5M的数据,是一个生成器 for chunk in file_obj.chunks(): f.write(chunk) return HttpResponse('ok') JsonResponse发送json类型的数据 from django.http import JsonResponse 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 == 'chao' and pwd == '123': ret_data['status'] = 1000 # 状态码 ret_data['msg'] = '登录成功!' else: ret_data['status'] = 1001 # 状态码 ret_data['msg'] = '登录失败!' # 方式一 ,关闭ensure_ascii后不乱码 # ret_data_json = json.dumps(ret_data,ensure_ascii=False) # return HttpResponse(ret_data_json) # 方式二,指定响应头 # return HttpResponse(ret_data_json,content_type='application/json') # 方式三 return JsonResponse(ret_data) # 非字典类型数据,需要加上 safe=False参数,否则认为是不合法的 #ret_data=[0,1,'a'] #return JsonResponse(ret_data,safe=False) jsontest.html <script> $.ajax({ url:'{% url "jsontest" %}',// data:{username:uname,//序列化 //data:JSON.stringify({username:uname,password:pwd}),data:{username:uname,headers:{ // contentType:'application/json',"X-CSRFToken":$.cookie('csrftoken'),success:function (res) { {#console.log(res,typeof res); // statusmsg {"status": 1001,"msg": "登录失败"}#} // 方式一:反序列化 {#var res = JSON.parse(res); //-- json.loads()#} // 方式二、三 console.log(res,typeof res); //直接就是反序列化之后的了 //JSON.stringify() -- json.dumps if (res.status === 1000){ // $('.error').text('登录成功'); location.href = '/home/'; // http://127.0.0.1:8000/home/ } else{ $('.error').text(res.msg); } } }) </script> SweetAlert插件--对话框{% load static %} <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="{% static 'bootstrap-3.3.0-dist/dist/css/bootstrap.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="{% static 'bootstrap-3.3.0-dist/dist/jQuery/jquery-3.1.1.js' %}"></script> <script src="{% static 'bootstrap-3.3.0-dist/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> (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |