django学习第十二天--ajax请求和csrftoken认证的三种方式
1|0基于cookie的登录认证装饰器
def check_login(f): def inner(request,*args,**kwargs): is_login = request.COOKIES.get('is_login') if is_login == 'True': ret = f(request) return ret else: return redirect('login') return inner @check_login def cart(request): return render(request,'cart.html')
2|0基于session的登录认证装饰器
def check_login(f): def inner(request,*args,**kwargs): is_login = request.session.get('is_login') if is_login: ret = f(request,*args,**kwargs) return ret else: return redirect('login') return inner @check_login def cart(request): return render(request,'cart.html')
3|0sweetalert插件完成ajax删除数据动作
3|1局部刷新页面进行删除 参考图书管理系统基于ajax请求删除数据
sweetalert基于bootstrap,所有首先要先导入bootstrap插件,然后把sweetalert下载下来,一般前端开发人员会把插件放在dist文件夹里面,所有我们只要用dist文件夹里面的插件就可以了,其他的都不要 {% 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' %}"> //sweetalert插件css </head> <body> <button class="btn btn-danger">删除啦</button> </body> <script src="{% static '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> //sweetalert插件js </html>
$('.del').on('click',function(){ var delete_id = $(this).prev().text() //获取上一个标签的id var ths = $(this); //因为下面的函数中this指向的不是我们的标签按钮,所以通过一个全部变量来保存一下这个$(this),方便后面使用 swal({ //这个sweetalert内部源码 直接拿来用就行,修改下文本内容 title:'are you sure?', text:'要谨慎!', type:'warning', showCancalButton:true, confirmButtonClass:'btn-danger', confirmButtonText:'确定删除', cancelButtonText:'容我三思', closeOnConfirm:false }, //点击确认删除时触发的函数 function(){ $.ajax({//路径拼接相当于/ajax_delete_book/1/ url:'/ajax_delete_book/'+delete_id+'/', type:'get', success:function(res){ console.log(res); if (res==='ok'){ //关闭弹窗 swal('删除成功!','你可以准备跑路了!','success');//这个是swal自带的方法 //局部刷新,删除对应记录 ths.parent().parent().remove(); } } }) } ) })
3|2js中的箭头函数
普通函数:var k = function(参数){return 'kkk'}; 箭头函数:var k =(参数) =>{return 'kkkk'}; 箭头函数简写:var k = (参数) => 'kkkk'
3|3js函数中this的指向问题,面试题
- 1.箭头函数 会去寻找上下文的this
var a = 'xx'; var d1 = { a:'ss', f:()=>{ //this指向函数调用者 console.log(this.a); //xx }, } d1.f() #调用者是d1对象,但是里面是箭头函数,所以会去往d1对象上面寻找,即window对象,所以打印的内容为xx
- 2.函数的单体模式
var a = 'xx'; var d1 = { a:'ss', f(){ console.log(this.a); }, } d1.f() #调用者是d1对象,打印结果为ss
- 3.没有对象调用,那么this指向的就是window对象
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()
- 4.箭头函数,改变this的指向,将this指向上下文的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() 首先d1.f(),d1对象调用f普通函数,那么里面首先会打印ss,然后f1()函数没有调用者,而且还是一个箭头函数,那么就会从上下文寻找this对象,即上一个调用者,即为d1,所以所以f1()函数里面指向的this就为d1,打印结果就为ss
- 5.嵌套箭头函数
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() 首先d1.f()调用的是箭头函数,那么就会往上找,即为window对象,所以调用f会打印xx,然后里面又嵌套了一个箭头函数f1,所以f1也会往上找,f1->d1->window,所以f1中this的指向也是window,打印结果为xx
4|0ajax处理请求失败和请求成功的方式
- html部分代码
$(".del").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:'/ajax_delete_book/'+'100'+'/',//这边暂时写死了100目的是要处理返回请求失败的结果,100对应的其实是要删除的id type:'get', success:function(res){ //当状态码为2xx或者3xx时才认为是请求正常成功了,会触发success对应的函数,但是当状态为4xx/5xx的时候,ajax认为此次请求是失败的会触发error属性对应的函数 if (res==='ok'){ console.log('okokok'); //关闭弹框 swal('删除成功!','你可以准备跑路了!','success'); //局部刷新,删除对应记录 ths.parent().parent().remove(); }else{ console.log('出错啦!') } }; error:function(res){ if (res.status===404){ swal('删除失败!',res.responseText,'error'); //res.responseText是后台响应回来的错误信息 } } } })
- views视图代码
def ajax_delete_book(request,pk): try: models.Book.objects.get(pk=pk).delete() except: return HttpResponse('找不到对应的资源!!!',status=404)#将响应状态码改为404 return HttpResponse('OK')
5|0CSRF跨站请求
如何防止csrf攻击呢?我们自己的网站要防止这个事情 csrftoken机制,csrf攻击的最多的方式 django已经做好了这个机制 如下图
6|0form表单通过csrftoken认证
- login.html文件
<form action='/login/' method='post'> {% csrf_token %} //会生成一个隐藏的input标签,value属性里面放着token值,name属性值为csrfmiddlewaretoken 用户名:<input type='text' name='username'> <input type='submit'> </form> {% csrf_token %}当我们使用from表单标签来发送请求时,如果需要csrftoken认证,那么必须将它写到我们的form表单标签里面,里面的任意位置。 生成的隐藏标签为: <input type="hidden" name="csrfmiddlewaretoken" value="WVHKQeAuMS4RGqyLybryIBAfacDa1Dp7PEaB3Badv3y0fvLqydX36xAVen6z3oS4">
6|1校验过程解释
html页面中的 {% csrf_token %} <input type="hidden" name="csrfmiddlewaretoken" value="WVHKQeAuMS4RGqyLybryIBAfacDa1Dp7PEaB3Badv3y0fvLqydX36xAVen6z3oS4"> cookie中的 csrftoken:CeFG6SA8Y8hcHAX5R93sxrS37v3iFFlcvX8xjfaRHjLlgFaKRbzXVnSJbGwHHqO9 注意:它们两个的token值是不相同的,这个不用管,到时发送给后台的时候,django会处理的 django会取出提交数据部分的token值和cookie中的token值进行比较: WVHKQeAuMS4RGqyLybryIBAfacDa1Dp7PEaB3Badv3y0fvLqydX36xAVen6z3oS4 --前32位可以对后面的几位进行解密,html中的token解密出secret_key1 一个字符串 CeFG6SA8Y8hcHAX5R93sxrS37v3iFFlcvX8xjfaRHjLlgFaKRbzXVnSJbGwHHqO9 --前32位可以对后面的几位进行解密,cookie中的token解密出secret_key2 一个字符串 secret_key1 = secret_key2 说明: token字符串的前32位是salt盐,后面是加密后的token,通过salt能解密出唯一的secret。 django会验证表单中的token和cookie中的token是否能解出同样的secret,secret一样则本次请求合法。 MIDDLEWARE = [ ... 'django.middleware.csrf.CsrfViewMiddleware', ... ] 源码 def _compare_salted_tokens(request_csrf_token, csrf_token): # Assume both arguments are sanitized -- that is, strings of # length CSRF_TOKEN_LENGTH, all CSRF_ALLOWED_CHARS. return constant_time_compare( _unsalt_cipher_token(request_csrf_token), _unsalt_cipher_token(csrf_token), ) def _unsalt_cipher_token(token): """ Given a token (assumed to be a string of CSRF_ALLOWED_CHARS, of length CSRF_TOKEN_LENGTH, and that its first half is a salt), use it to decrypt the second half to produce the original secret. """ salt = token[:CSRF_SECRET_LENGTH] token = token[CSRF_SECRET_LENGTH:] chars = CSRF_ALLOWED_CHARS pairs = zip((chars.index(x) for x in token), (chars.index(x) for x in salt)) secret = ''.join(chars[x - y] for x, y in pairs) # Note negative values are ok return secret
7|0ajax请求通过csrftoken认证三种方式
- 方式1
首先在html文件中间,写上{% csrf_token %} {% csrf_token %} 用户名: <input type="text" id="uname" > <button id="btn">ajax提交</button> jquey代码 $('#btn').click(function(){ var uname = $('#uname').val(); //获取csrfmiddlewaretoken的input标签value属性对应的值 var token = $('[name="csrfmiddlewaretoken"]').val(); $.ajax({ url:'/login/', type:'post', //将token值放到请求数据部分,token的键必须是csrfmiddlewaretoken data:{uname:uname,csrfmiddlewaretoken:token}, success:function(res){ console.log(res); } }) })
- 方式2
使用'{{ csrf_token }}'这个模板渲染标签,这样就不要我们在html页面中写{% csrf_token %}了。 $('#btn').click(function(){ var uname = $('#uname').val(); //直接就能得到csrfmiddlewaretoken的input标签value属性的值 var token= '{{ csrf_token }}'; $.ajax({ url:'/login/', type:'post', data:{uname:uname,csrfmiddlewaretoken:token}, success:function(res){ console.log(res); } }) })
- 方式3
借助js操作cookie的方法来获取到cookie中的csrftoken那个键对应的值 然后将这个值组成一个请求头,放到此次请求中 headers:{'X-CSRFToken':这个值} 这个值,通过js能够获取到,通过jquery也能获取到,我们看一下jquery如何操作cookie 操作步骤,下载与引入 jquery.cookie.js基于jquery;先引入jquery,再引入:jquery.cookie.js;下载:http://plugins.jquery.com/cookie/ <script src="{% static 'jquery.js' %}"></script> #这个要在上面 <script src="{% static 'jquery.cookie.js' %}"></script> {% csrf_token %} //需要在html中写上{% csrf_token %}或{{ csrf_token }},不然此次获取这个html页面的时候,响应中不会有这个csrftoken的cookie的值 $('#btn').click(function(){ var uname = $('#uname').val(); //通过js获取jquery来获取cookie中的csrftoken这个键对应的token值 var token = $.cookie('csrftoken'); $.ajax({ url:'/login/', type:'post', //将获取到的token值放到请求头中,这个请求头键值对的键必须是'X-CSRFToken' headers:{ 'X-CSRFToken':token, }, //django先去获取请求数据部分的token值,获取不到,就去找一个叫做X-CSRFToken请求头键值对,它的值和cookie中的csrftoken的值要相等。 data:{uname:uname,}, success:function(res){ console.log(res); } }) })
8|0ajax上传文件
- html文件
用户名:<input type='text' name='username'> 密码:<input type='text' name='password'> 头像:<input type='file' name='touxiang'> <button id='sub'>上传</button> js部分 $('$sub').click(function(){ //ajax上传文件必须依赖于FormData对象 var formdata = new FormData(); var uname = $('[name="username"]').val(); var pwd = $('[name="password"]').val(); //获取浏览器上的文件数据方法:$('[name="touxiang"]')[0].files[0] var file_obj = $('[name="touxiang"]')[0].files[0]; formdata.append('uname',uname)//后面取数据也是用request.POST.get('uname') formdata.append('pwd',pwd) formdata.append('csrfmiddlewaretoken','{{ csrf_token }}') //request.FILES formdata.append('touxiang',file_obj) $.ajax({ url:'',//如果路径为空,那么使用当前页面的路径,也就是往当前路径下进行提交 type:'post', data:formdata, //下面的两个参数的意思是,不要对数据进行任何的预处理和加工 processData:false, contentType:false, success:function(res){ console.log(res); } }) })
- views文件
def upload(request): if request.method == 'GET': return render(request,'upload.html') else: print(request.POST) print(request.FILES) file_obj = request.FILES.get('touxiang') with open(file_obj.name,'wb') as f: for i in file_obj: f.write(i) //第二种写法 //默认一次返回大小为65536B,也就是64KB,最大2.5M for chunk in file_obj.chunks(): f.write(chunk) return HttpResponse('ok')
9|0上传多文件 自行拓展 后续补充
- html文件
<input type='file' name='touxiang' multiple> //multiple为上传多个
__EOF__

本文作者:404 Not Found
本文链接:https://www.cnblogs.com/weiweivip666/p/13388024.html
关于博主:可能又在睡觉
版权声明:转载请注明出处
声援博主:如果看到我睡觉请喊我去学习
本文链接:https://www.cnblogs.com/weiweivip666/p/13388024.html
关于博主:可能又在睡觉
版权声明:转载请注明出处
声援博主:如果看到我睡觉请喊我去学习
-------------------------------------------
个性签名:代码过万,键盘敲烂!!!
如果觉得这篇文章对你有小小的帮助的话,记得在右下角点个“推荐”哦,博主在此感谢!
分类:
Django学习基于1.11版本
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人