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對象和字符串轉換的兩個方法:css

    • 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

常見應用情景

搜索引擎根據用戶輸入的關鍵字,自動提示檢索關鍵字。html

註冊時候的用戶名的查重jquery


整個過程當中頁面沒有刷新,只是刷新頁面中的局部位置ajax

當請求發出後,瀏覽器還能夠進行其餘操做,無需等待服務器的響應數據庫

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 的參數寫入也較爲麻煩,django

回調方法還須要進行自行的狀態判斷, 此方法瞭解便可. json

jQuery實現的AJAX

語法

settings  本次ajax請求須要的全部的參數,值爲 JS對象flask

$.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) 
相關文章
相關標籤/搜索