Django JSON,AJAX
JSON
概念
- JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
- JSON 是轻量级的文本数据交换格式
- JSON 独立于语言 *
- JSON 具有自我描述性,更易理解
示例
- ["one", "two", "three"]
- { "one": 1, "two": 2, "three": 3 }
- {"names": ["张三", "李四"] }
- [ { "name": "张三"}, {"name": "李四"} ]
格式不正确的示例
- { name: "张三", 'age': 32 } // 属性名必须使用双引号
- [32, 64, 128, 0xFFF] // 不能使用十六进制值
- { "name": "张三", "age": undefined } // 不能使用undefined
- { "name": "张三","birthday": new Date('Fri, 26 Aug 2011 07:13:10 GMT'),"getName": function() {return this.name;} // 不能使用函数和日期对象}
相关方法
JavaScript中关于JSON对象和字符串转换的两个方法:
-
- JSON.parse(): 用于将一个 JSON 字符串转换为 JavaScript 对象
- JSON.parse('{"name":"Q1mi"}');
- JSON.parse('{name:"Q1mi"}') ; // 错误
- JSON.parse('[18,undefined]') ; // 错误
-
- JSON.stringify(): 用于将 JavaScript 值转换为 JSON 字符串。
- JSON.stringify({"name":"Q1mi"})
和XML的比较
- 书写简单
- 一目了然
- 可以由解释引擎直接处理
- 无需另外添加解析代码
AJAX
概念
- 使用Javascript语言与服务器进行异步交互进行传输的数据的传输
- 在不重新加载整个页面的情况下,可以与服务器交换数据并更新部分网页内容。
- 无需要任何浏览器插件,但需要用户允许JavaScript在浏览器上执行。
- 同步交互:客户端发出一个请求后,需要等待服务器响应结束后,才能发出第二个请求;
- 异步交互:客户端发出一个请求后,无需等待服务器响应结束,就可以发第二个请求
示例
1 // HTML部分代码 2 !DOCTYPE html> 3 <html lang="en"> 4 <head> 5 <meta charset="UTF-8"> 6 <meta http-equiv="x-ua-compatible" content="IE=edge"> 7 <meta name="viewport" content="width=device-width, initial-scale=1"> 8 <title>AJAX局部刷新实例</title> 9 </head> 10 <body> 11 12 <input type="text" id="i1">+ 13 <input type="text" id="i2">= 14 <input type="text" id="i3"> 15 <input type="button" value="AJAX提交" id="b1"> 16 17 <script src="/static/jquery-3.2.1.min.js"></script> 18 <script> 19 $("#b1").on("click", function () { 20 $.ajax({ 21 url:"/ajax_add/", 22 type:"GET", 23 data:{ 24 "i1":$("#i1").val(), 25 "i2":$("#i2").val() 26 }, 27 success:function (data) { 28 $("#i3").val(data); 29 } 30 }) 31 }) 32 </script> 33 </body> 34 </html> 35 36 37 # views.py 38 def ajax_demo1(request): 39 return render(request, "ajax_demo1.html") 40 41 42 def ajax_add(request): 43 i1 = int(request.GET.get("i1")) 44 i2 = int(request.GET.get("i2")) 45 ret = i1 + i2 46 return JsonResponse(ret, safe=False) 47 48 49 urls.py 50 urlpatterns = [ 51 ... 52 url(r'^ajax_add/', views.ajax_add), 53 url(r'^ajax_demo1/', views.ajax_demo1), 54 ... 55 ]
常见应用情景
搜索引擎根据用户输入的关键字,自动提示检索关键字。
注册时候的用户名的查重
整个过程中页面没有刷新,只是刷新页面中的局部位置
当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应
AJAX的优缺点
优点:
- AJAX使用JavaScript技术向服务器发送异步请求;
- AJAX请求无须刷新整个页面;
- 因为服务器响应内容不再是整个页面,而是页面中的部分内容,更加专一
缺点 :
- 请求杂乱且数量增加,对服务器的压力增加
传统方式 实现 AJAX
common.js
function createXhr(){ var xhr = null; if(window.XMLHttpRequest){ xhr = new XMLHttpRequest(); }else{ xhr = new ActiveXObject("Microsoft.XMLHttp"); } return xhr; }
01-ajax-get.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <button onclick="btnAjx()">点击发送 ( ajax )</button> <a href="/01-server">发生 ( 非 ajax )</a> <div id="show">123</div> <script src="/static/js/common.js"></script> <script src="/static/js/jquery-1.11.3.js"></script> </body> </html> <script> function btnAjx() { // 1.获取 xhr 对象 var xhr = createXhr(); // 2.创建请求 xhr.open('get', '/01-server', true); // 3.设置回调函数 xhr.onreadystatechange = function () { // 判断 readyState 以及 status 值 if (xhr.readyState == 4 && xhr.status == 200) { // 接收响应数据 var resT = xhr.responseText; $("#show").html(resT); } } // 4.发送请求 xhr.send(null); } </script>
app.py
from flask import Flask, render_template app = Flask(__name__) @app.route('/01-ajax-get') def ajax_get(): return render_template("01-ajax-get.html") @app.route('/01-server') def server01(): return "这是使用 ajax 方式发送的请求" if __name__ == '__main__': app.run()
可见较为繁琐. 需要手动写一个 创建方法, 然后ajax 的参数写入也较为麻烦,
回调方法还需要进行自行的状态判断, 此方法了解即可.
jQuery实现的AJAX
语法
settings 本次ajax请求需要的所有的参数,值为 JS对象
$.ajax(url[,settings]);
常用参数
url 字符串,表示异步请求的地址
type 字符串,表示的是请求方式, get 或 post
data 传递到服务器端的参数 ( 字符串 / json 对象 )
async 使用异步还是同步的方式发送请求
- true : 使用异步的方式
- false : 使用同步的方式
dataType 字符串,表示的是响应回来的数据的格式
- 'html'
- 'xml'
- 'text'
- 'script'
- 'json' 响应回来的数据时JSON类型的
- 'jsonp' 跨域的时候使用
- success 请求和响应成功后的回调函数
success 成功拿到数据后的进行的回调函数
error 请求或响应失败时的回调函数
beforeSend 发送请求之前执行的回调函数
如果该函数中return false 的话则终止请求的发送
function(data){} 方法. data 表示回传的数据, 必须配合上面三个来
全部参数
名称 | 值/描述 |
---|---|
async | 布尔值,表示请求是否异步处理。默认是 true。 |
beforeSend(xhr) | 发送请求前运行的函数。 |
cache | 布尔值,表示浏览器是否缓存被请求页面。默认是 true。 |
complete(xhr,status) | 请求完成时运行的函数(在请求成功或失败之后均调用,即在 success 和 error 函数之后)。 |
contentType | 发送数据到服务器时所使用的内容类型。默认是:"application/x-www-form-urlencoded"。 |
context | 为所有 AJAX 相关的回调函数规定 "this" 值。 |
data | 规定要发送到服务器的数据。 |
dataFilter(data,type) | 用于处理 XMLHttpRequest 原始响应数据的函数。 |
dataType | 预期的服务器响应的数据类型。 |
error(xhr,status,error) | 如果请求失败要运行的函数。 |
global | 布尔值,规定是否为请求触发全局 AJAX 事件处理程序。默认是 true。 |
ifModified | 布尔值,规定是否仅在最后一次请求以来响应发生改变时才请求成功。默认是 false。 |
jsonp | 在一个 jsonp 中重写回调函数的字符串。 |
jsonpCallback | 在一个 jsonp 中规定回调函数的名称。 |
password | 规定在 HTTP 访问认证请求中使用的密码。 |
processData | 布尔值,规定通过请求发送的数据是否转换为查询字符串。默认是 true。 |
scriptCharset | 规定请求的字符集。 |
success(result,status,xhr) | 当请求成功时运行的函数。 |
timeout | 设置本地的请求超时时间(以毫秒计)。 |
traditional | 布尔值,规定是否使用参数序列化的传统样式。 |
type | 规定请求的类型(GET 或 POST)。 |
url | 规定发送请求的 URL。默认是当前页面。 |
username | 规定在 HTTP 访问认证请求中使用的用户名。 |
xhr | 用于创建 XMLHttpRequest 对象的函数。 |
实例
HTML
<script> $("#ajaxTest").click(function () { $.ajax({ url: "/ajax_test/", type: "POST", data: {username: "Q1mi", password: 123456}, success: function (data) { alert(data) } }) }) </script>
views.py
def ajax_test(request): user_name = request.POST.get("username") password = request.POST.get("password") print(user_name, password) return HttpResponse("OK")
urls.py
urlpatterns = [ ... url(r'^ajax_test/', views.ajax_test), ... ]
注意
$.ajax 参数 data参数中的键值对,如果值值不为字符串,需要将其转换成字符串类型。 $("#b1").on("click", function () { $.ajax({ url:"/ajax_add/", type:"GET", data:{ "i1":$("#i1").val(), "i2":$("#i2").val(), "hehe": JSON.stringify([1, 2, 3])}, success:function (data) { $("#i3").val(data); } }) })
AJAX请求如何设置csrf_token
form 表单提提交数据必须要带scrfToken,哪怕在ajax里面提交也许带这一字段才可以
方法1
普通的 form 表单的 post 方式提交需要写一个 {% csrf_token %} 会自动生成一个 隐藏的 input 标签
跨域请求的时候需要此标签的的 csrfmiddlewaretoken 值
直接通过 jquery 方式取出此标签中的 csrfmiddlewaretoken 值放在data 中传递即可
$.ajax({ url: "/cookie_ajax/", type: "POST", data: { "username": "Q1mi", "password": 123456, "csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val() // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data中 }, success: function (data) { console.log(data); } })
方法2
单独写一个CSS文件(my_ajax_csrf.css)里面写下面代码
每次有AJAX 的时候就页面引用一下,其他什么都不用做了.
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');
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); } } });
方法3
当向服务器发送一次 post 请求但是并不是通过 form 的方式, 但是只要是 post方式 数据的提交依然是需要 csrf_token
但是不是 form 的方式也么办法在页面中直接加 {% csrf_token %}, 所以也没办法通过{% csrf_token %}生成的隐藏标签来取其值
只能在 ajax 中携带的数据中直接加一个 csrfmiddlewaretoken: '{{csrf_token}}' 也可以实现
$('.jsDeleteFav_course').on('click', function () { var _this = $(this), favid = _this.attr('data-favid'); $.ajax({ cache: false, type: "POST", url: "/org/add_fav/", data: { fav_type: 1, fav_id: favid, csrfmiddlewaretoken: '{{csrf_token}}' }, async: true, success: function (data) { Dml.fun.winReload(); } }); });
ajax 上传文件
ajax 对于 上传文件 的时候一样 有特殊的操作
需要加两个参数
- processData: false,
- contentType: false,
以及
- data 必须是 FormDate 类型 不能再手动创建一个随意的 data 了
具体示例可见综合示例中的 头像文件上传
AJAX 注册综合示例
1 ajax 注册示例 2 3 # 注册的视图函数 4 def register(request): 5 if request.method == "POST": 6 ret = {"status": 0, "msg": ""} 7 form_obj = forms.RegForm(request.POST) 8 print(request.POST) 9 # 帮我做校验 10 if form_obj.is_valid(): 11 # 校验通过,去数据库创建一个新的用户 12 # 传过来的字段里面有个 re_password 字段是无法入库的给去掉 13 # 关于这个 cleaned_data 的功能为提取出来字典里面的值 14 form_obj.cleaned_data.pop("re_password") 15 avatar_img = request.FILES.get("avatar") 16 # 因为现在的userinfo 17 models.UserInfo.objects.create_user(**form_obj.cleaned_data, avatar=avatar_img) 18 ret["msg"] = "/index/" 19 return JsonResponse(ret) 20 else: 21 print(form_obj.errors) 22 ret["status"] = 1 23 ret["msg"] = form_obj.errors 24 print(ret) 25 print("=" * 120) 26 return JsonResponse(ret) 27 # 生成一个form对象 28 form_obj = forms.RegForm() 29 print(form_obj.fields) 30 return render(request, "register.html", {"form_obj": form_obj}) 31 32 33 // AJAX提交注册的数据 34 <script> 35 $("#reg-submit").click(function () { 36 // 取到用户填写的注册数据,向后端发送AJAX请求 37 var formData = new FormData(); 38 formData.append("username", $("#id_username").val()); 39 formData.append("password", $("#id_password").val()); 40 formData.append("re_password", $("#id_re_password").val()); 41 formData.append("email", $("#id_email").val()); 42 // 上传文件的数据需要用 files 拿到 43 formData.append("avatar", $("#id_avatar")[0].files[0]); 44 formData.append("csrfmiddlewaretoken", $("[name='csrfmiddlewaretoken']").val()); 45 46 $.ajax({ 47 url: "/reg/", 48 type: "post", 49 // 上传文件的时候需要加这两个 fales 50 processData: false, 51 contentType: false, 52 data: formData, 53 success:function (data) { 54 if (data.status){ 55 // 有错误就展示错误 56 // console.log(data.msg); 57 // 将报错信息填写到页面上 58 $.each(data.msg, function (k,v) { 59 // console.log("id_"+k, v[0]); 60 // console.log($("#id_"+k)); 61 // 链式操作 先加值然后找父类 加属性 62 $("#id_"+k).next("span").text(v[0]).parent().parent().addClass("has-error"); 63 }) 64 65 }else { 66 // 没有错误就跳转到指定页面 67 location.href = data.msg; 68 } 69 } 70 }) 71 }); 72 73 74 // 将所有的input框绑定获取焦点的事件,将所有的错误信息清空 75 $("form input").focus(function () { 76 $(this).next().text("").parent().parent().removeClass("has-error"); 77 }) 78 79 </script>
序列化
Django内置的serializers
可以更加便携进行序列化,当然可以用 json 模块完成
待补充 这个方法是内置的比较粗糙的,实际上很少被使用.
1 from django.core import serializers 2 3 def books_json(request): 4 book_list = models.Book.objects.all()[0:10] 5 6 7 ret = serializers.serialize("json", book_list) # 第一个参数为转换的格式,后一个参数为被转换的变量 8 return HttpResponse(ret)
本文来自博客园,作者:羊驼之歌,转载请注明原文链接:https://www.cnblogs.com/shijieli/p/10082818.html