ajax
stringify与parse方法
JavaScript中关于JSON对象和字符串转换的两个方法:
JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象
JSON.parse('{"name":"alex"}'); JSON.parse('{name:"alex"}') ; // 错误 JSON.parse('[18,undefined]') ; // 错误
JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。
JSON.stringify({"name":"alex"})
python中数据类型的转化 1. python对象 ——》 json字符串 import json json.dumps(python的数据类型) 2. json字符串 ——》python对象 json.loads(json字符串) 3.支持的数据类型 字符串 数字 布尔值 列表 字典 None django在视图函数中发送json格式的数据 1,使用json模块 json.dumps() ,ajax还需要进行json解析 #views.py return HttpResponse(json.dumps({"msg":"ok!"})) #index.html var data=json.parse(data) console.log(data.msg); 2,使用 JsonResponse 可以发送字典,两边都不需要进行json的序列化与反序列化,ajax接受的直接是一个对象 #views.py from django.http import JsonResponse return JsonResponse({"msg":"ok!"}) #index.html console.log(data.msg); JsonResponse 对象: class JsonResponse(data, encoder=DjangoJSONEncoder, safe=True, json_dumps_params=None,**kwargs) 这个类是HttpRespon的子类,它主要和父类的区别在于: a).它的默认Content-Type 被设置为: application/json b).第一个参数,data应该是一个字典类型,当 safe 这个参数被设置为:False ,那data可以填入任何能被转换为JSON格式的对象,比如list, tuple, set。 默认的safe 参数是 True. 如果你传入的data数据类型不是字典类型,那么它就会抛出 TypeError的异常。 c).json_dumps_params参数是一个字典,它将调用json.dumps()方法并将字典中的参数传入给该方法。 3,使用Django内置的serializers模块,可以发送queryset数据库对象 def books_json(request): book_list = models.Book.objects.all()[0:10] from django.core import serializers ret = serializers.serialize("json", book_list) return HttpResponse(ret)
ajax
AJAX 最大的优点是在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。(这一特点给用户的感受是在不知不觉中完成请求和响应过程)
向服务端发请求的方法:
1. 在浏览器的地址栏上输入URL 回车 —— 》GET
2. 使用form表单 提交 —— 》 GET/POST
1. action # 提交的地址
2. method # 提交方式
3. 上传文件的时候 enctype="multipart/form-data"
4. input标签要有name属性
5. 要有一个type=sumbit的按钮或者input
3. a标签 —— 》GET
4. Ajax
使用ajax局部刷新页面例子,计算两个数相加之和 浏览器获取两个数,通过ajax发送到后端,后端相加后将结果返回给浏览器,浏览器的结果框局部刷新渲染这个结果
csrf验证是防止别的程序发post请求到我的网址,对于自己写的网页我们给每个访问网址的浏览器加上一个cookie,然后让我们的程序发post请求时也带一个cookie,当浏览器发请求时经过中间件 process_request获取浏览器带的cookie,然后process_view获取了post请求中的cookie,并和浏览器带的cookie进行比较,一致允许访问,不一致拒绝访问
在post表单中加{% csrf_token %} 可以给post中带cookie,并给浏览器中加cookie
给views中的函数加装饰器 @ensure_csrf_cookie ,也可以给浏览器加cookie, CBV的views只能把装饰器加到 dispatch() 方法上
# 不考虑csrf的ajax提交post请求(注掉中间件) # 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'^index/', views.index), url(r'^calc/', views.calc), ] # views.py from django.shortcuts import render,HttpResponse def index(request): return render(request,'index.html') def calc(request): l1 = int(request.POST.get('i1')) l2 = int(request.POST.get('i2')) res = l1+l2 return HttpResponse(res) # index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>ajex提交</h2> <input type="text" id="i1">+ <input type="text" id="i2">= <input type="text" id="i3"> <button type="submit" id="b1">计算</button> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script> $('#b1').click(function () { var i1=$('#i1').val(); var i2=$('#i2').val(); $.ajax({ url:'/calc/', # 请求地址是 /calc/ type:'post', data:{ 'i1':i1, 'i2':i2 }, success:function (res) { # res是 calc函数的返回值,calc返回的是相加后的结果,这里接收 console.log(res); $('#i3').val(res); } }) }) </script> </body> </html>
# 考虑csrf的情况,需要给ajax的post请求加上cookie 方法一:通过获取隐藏的input标签中的csrfmiddlewaretoken值,放置在data中发送。 # index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h2>ajex提交</h2> {% csrf_token %} <input type="text" id="i1">+ <input type="text" id="i2">= <input type="text" id="i3"> <button type="submit" id="b1">计算</button> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script> $('#b1').click(function () { var i1=$('#i1').val(); var i2=$('#i2').val(); $.ajax({ url:'/calc/', type:'post', data:{ 'i1':i1, 'i2':i2, "csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val() // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data中 }, success:function (res) { console.log(res); $('#i3').val(res); } }) }) </script> </body> </html> 方法二:通过获取返回的cookie中的字符串 放置在请求头中发送 ... {% csrf_token %} ... $.ajax({ url:'/calc/', type:'post', headers:{"X-CSRFToken":$.cookie('csrftoken')}, //从Cookie取csrftoken,并设置到请求头中 data:{ 'i1':i1, 'i2':i2, }, success:function (res) { console.log(res); $('#i3').val(res); } }) ... 方法三:自己写一个getCookie的js文件 因为是js文件需要放到静态文件中,所以把以下代码写在static目录下,然后命名为ajax_setup.js ,然后在index.html页面链接js <script src="/static/ajax_setup.js"></script> function getCookie(name) { var cookieValue = null; if (document.cookie && document.cookie !== '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = jQuery.trim(cookies[i]); // Does this cookie string begin with the name we want? if (cookie.substring(0, name.length + 1) === (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } var csrftoken = getCookie('csrftoken'); // 每一次都这么写太麻烦了,可以使用$.ajaxSetup()方法为ajax请求统一设置 function csrfSafeMethod(method) { // these HTTP methods do not require CSRF protection return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method)); } $.ajaxSetup({ beforeSend: function (xhr, settings) { if (!csrfSafeMethod(settings.type) && !this.crossDomain) { xhr.setRequestHeader("X-CSRFToken", csrftoken); } } }); 如果使用从cookie中取csrftoken的方式,需要确保cookie存在csrftoken值。 如果你的视图渲染的HTML文件中没有包含 {% csrf_token %},Django可能不会设置CSRFtoken的cookie。 这个时候需要使用ensure_csrf_cookie()装饰器强制设置Cookie。 推荐在 views 函数里加装饰器,然后在模板中就不用写 {% csrf_token %} 了 django.views.decorators.csrf import ensure_csrf_cookie @ensure_csrf_cookie def login(request): pass
# 上传文件 # 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'^ajax_file/', views.ajax_file), url(r'^form_file/', views.form_file), ] # views.py def form_file(request): if request.method == 'POST': file_obj = request.FILES.get('file') with open(file_obj.name,'wb') as f: for i in file_obj.chunks(): # 使用chunks()函数可以一点一点上传 f.write(i) return HttpResponse('上传成功') return render(request,'form_file.html') def ajax_file(request): file_obj = request.FILES.get('f1') with open(file_obj.name,'wb') as f: for i in file_obj.chunks(): f.write(i) return HttpResponse('上传成功') # form_file.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> {#-------------------使用form表单上传文件-----------------#} <form action="" method="post" enctype="multipart/form-data"> # 需要指定enctype = 'multipart/form-data',不然默认的是下面的,会把我们上传的文件以键值对的形式(和url类似)拼接,然后放到请求体中 {#<form action="" method="post" enctype="application/x-www-form-urlencoded">#} {% csrf_token %} <input type="file" name="file"> <button>上传</button> </form> <hr> {#--------------------使用ajax上传文件--------------------------#} <h2>ajax上传文件</h2> <input type="file" name="file" id="f1"> <button id="b1">上传</button> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script> $("#b1").click(function () { var formData = new FormData(); formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val()); formData.append("f1", $("#f1")[0].files[0]); {# $("#f1")[0] 把jquery对象变为js对象#} $.ajax({ url: "/ajax_file/", {# 转向ajax_file路径,向这个路径发送请求 #} type: "POST", processData: false, // 告诉jQuery不要去处理发送的数据 contentType: false, // 告诉jQuery不要去设置Content-Type请求头 data: formData, success: function (data) { console.log(data) } }) }) </script> </body> </html> # 使用json发送字符串 def ajax_test(request): print(request.POST) print(request.POST.get('name')) print(request.POST.get('hobby'),type(request.POST.get('hobby'))) d = {'status':0,'msg':''} # return HttpResponse(json.dumps(d)) return JsonResponse(d) # JsonResponse直接以json格式发送字典
# 用户名注册,从数据库匹配用户名是否存在,如果存在提示,不存在注册
# 用户名注册,从数据库匹配用户名是否存在,如果存在提示,不存在注册 # views.py def reg(request): ret = {'status': 0, 'msg': ''} if request.is_ajax(): name = request.POST.get('username') is_exist = models.UserInfo.objects.filter(username=name) if is_exist: ret['msg'] = '用户名已存在' ret['status'] = 1 else: ret['msg'] = '用户名可以使用' return JsonResponse(ret) return render(request, 'reg.html') # reg.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="x-ua-compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Title</title> </head> <body> <input type="text" id="i1"><span style="color: red"></span> <button id="b1">点击</button> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script src="/static/ajax_setup.js"></script> <script> $("#i1").blur(function () { <!-- i1失焦时,发送ajax请求--> var _this = $(this); $.ajax({ url: '/reg/', type: 'post', data: {'username': $("#i1").val()}, success: function (res) { console.log(res); if (res.status != 0) { _this.next().text(res.msg); <!--next指的是下一个标签--> } } }) }); $("#i1").focus(function () { <!-- i1聚焦时,清空span标签的内容--> $(this).next().text('') <!-- input标签改变文本内容使用 .val(文本内容) span标签改变文本内容 .text(文本内容)--> }) </script> </body> </html>
# 使用ajax的方式删除班级对象,当点击删除按钮时,通过ajex把班级对象的id传给后端,然后后端在数据库中删除这个班级对象,将成功的结果返回给ajax,然后前端删除该班级标签
# 使用ajax的方式删除每个班级对象 # html文件 <div class="table-responsive"> <table class="table table-striped"> <thead> <tr> <th>序号</th> <th>ID</th> <th>班级</th> <th>操作</th> </tr> </thead> <tbody> {% for class in class_list %} <tr data_id={{ class.id }}> <td>{{ forloop.counter }}</td> <td>{{ class.id }}</td> <td>{{ class.name }}</td> <td> <span class="btn btn-danger btn-sm "> <i class="fa fa-trash-o fa-fw"></i>删除 </span> <a class="btn btn-success btn-sm" href="/edit_class/?id={{ class.id }}"> <i class="fa fa-edit fa-fw"></i>编辑 </a> </td> </tr> {% empty %} <tr> <td colspan="4" style="text-align: center">没有数据</td> </tr> {% endfor %} </tbody> </table> </div> <!--使用sweetalert插件,可以显示弹窗--> <script src="/static/plugins/dist/sweetalert.min.js"></script> <link rel="stylesheet" href="/static/plugins/dist/sweetalert.css"> <!--jquery也用的到--> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script> $(".btn-danger").on("click", function (event) { _this = $(this); 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: "/del_class/", type: "post", data: {"id": deleteId}, success: function (data) { if (data.status === 1) { console.log(deleteId); console.log($(this), 'ajax中的this'); {#<!--#} {#w.fn.init [{…}]#} {#0:{url: "/del_class/", type: "POST", isLocal: false, global: true, processData: true, …}#} {#length:1#} {#__proto__:Object(0)#} {#ajax中的$(this)是ajax对象,包含了ajax中的参数;ajax外的$(this)才是我们选中的span对象(删除按钮)#} {#-->#} console.log(_this, 'ajax外的this'); {#<!--#} {#w.fn.init [span.btn.btn-danger.btn-sm]#} {#0:span.btn.btn-danger.btn-sm#} {#length:1#} {#__proto__:Object(0)-->#} _this.parent().parent().remove() {#$("[data_id=deleteId]").remove(); 测试用#} {#不知道为什么这样用属性选择器不能找到,不是属性选择器的问题,是deleteId的问题,因为把deleteId换成一个具体的数字就行了,可能是属性选择器后面的属性不能用变量,因为我发现放数字和放变量data_id在pycharm上的颜色不同#} swal("删除成功!", "你可以准备跑路了!", "success"); } else { swal("删除失败", "你可以再尝试一下!", "error") } }, }); }); }) </script> # views 中del_class函数 def del_class(request): del_class = request.POST.get('id') class_obj = models.Class.objects.get(id=del_class) class_obj.delete() data = {} data['status'] = 1 return JsonResponse(data)