TOP

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 ]
View Code

常见应用情景

搜索引擎根据用户输入的关键字,自动提示检索关键字。

注册时候的用户名的查重


整个过程中页面没有刷新,只是刷新页面中的局部位置

当请求发出后,浏览器还可以进行其他操作,无需等待服务器的响应

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> 
View Code

序列化

  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) 



 

posted @ 2018-12-07 14:38  羊驼之歌  阅读(360)  评论(0编辑  收藏  举报