Django基礎七之Ajax

一 Ajax簡介

1.簡介

    AJAX(Asynchronous Javascript And XML)翻譯成中文就是「異步的Javascript和XML」。即便用Javascript語言與服務器進行異步交互,傳輸的數據爲XML(固然,傳輸的數據不僅是XML,如今更多使用json數據)。html

    AJAX 不是新的編程語言,而是一種使用現有標準的新方法。python

    AJAX 最大的優勢是在不從新加載整個頁面的狀況下,能夠與服務器交換數據並更新部分網頁內容。(這一特色給用戶的感覺是在不知不覺中完成請求和響應過程)jquery

    AJAX 不須要任何瀏覽器插件,但須要用戶容許JavaScript在瀏覽器上執行。ajax

      a.同步交互:客戶端發出一個請求後,須要等待服務器響應結束後,才能發出第二個請求;django

      b.異步交互:客戶端發出一個請求後,無需等待服務器響應結束,就能夠發出第二個請求。編程

  AJAX除了異步的特色外,還有一個就是:瀏覽器頁面局部刷新;(這一特色給用戶的感覺是在不知不覺中完成請求和響應過程json

2.示例

    頁面輸入兩個整數,經過AJAX傳輸到後端計算出結果並返回。後端

    html文件名稱爲ajax_demo1.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>AJAX局部刷新實例</title>
</head>
<body>

<input type="text" id="i1">+
<input type="text" id="i2">=
<input type="text" id="i3">
<input type="button" value="AJAX提交" id="b1">

<script src="/static/jquery-3.2.1.min.js"></script>
<script>
  $("#b1").on("click", function () {
    $.ajax({
      url:"/ajax_add/", //別忘了加雙引號
      type:"GET",  
      data:{"i1":$("#i1").val(),"i2":$("#i2").val()}, //object類型,鍵值形式的,能夠不給鍵加引號
      success:function (data) {
        $("#i3").val(data);
      }
    })
  })
</script>
</body>
</html>

views.py裏面的內容:服務器

def ajax_demo1(request):
    return render(request, "ajax_demo1.html")


def ajax_add(request):
    #time.sleep(10)  #不影響頁面發送其餘的請求
    i1 = int(request.GET.get("i1"))
    i2 = int(request.GET.get("i2"))
    ret = i1 + i2
    return JsonResponse(ret, safe=False)
    #return render(request,'index.html')  #返回一個頁面沒有意義,就是一堆的字符串,拿到了這個頁面,你怎麼處理,你要作什麼事情,根本就沒有意義

 urls.py裏面的內容:

urlpatterns = [
    ...
    url(r'^ajax_add/', views.ajax_add),
    url(r'^ajax_demo1/', views.ajax_demo1),
    ...   
]

啓動django項目,而後運行看看效果,頁面不刷新

3.AJAX常見應用情景

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

還有一個很重要的應用場景就是註冊時候的用戶名的查重。

其實這裏就使用了AJAX技術!當文件框發生了輸入變化時,使用AJAX技術向服務器發送一個請求,而後服務器會把查詢到的結果響應給瀏覽器,最後再把後端返回的結果展現出來。

  a.整個過程當中頁面沒有刷新,只是刷新頁面中的局部位置而已!

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

當輸入用戶名後,把光標移動到其餘表單項上時,瀏覽器會使用AJAX技術向服務器發出請求,服務器會查詢名爲lemontree7777777的用戶是否存在,最終服務器返回true表示名爲lemontree7777777的用戶已經存在了,瀏覽器在獲得結果後顯示「用戶名已被註冊!」。

    a.整個過程當中頁面沒有刷新,只是局部刷新了;

    b.在請求發出後,瀏覽器不用等待服務器響應結果就能夠進行其餘操做;

4.AJAX的優缺點

優勢:

  1.AJAX使用JavaScript技術向服務器發送異步請求;

  2.AJAX請求無須刷新整個頁面;

  3.由於服務器響應內容再也不是整個頁面,而是頁面中的部份內容,因此AJAX性能高;

二 Ajax的使用

1.基於jQuery的實現

<button class="send_Ajax">send_Ajax</button>
<script>
       $(".send_Ajax").click(function(){
           $.ajax({
               url:"/handle_Ajax/",
               type:"POST",
               data:{username:"chao",password:123},
               success:function(data){
                   console.log(data)
               },
               error: function (jqXHR, textStatus, err) {
                        console.log(arguments);
                    },
               complete: function (jqXHR, textStatus) {
                        console.log(textStatus);
                },
               statusCode: {
                    '403': function (jqXHR, textStatus, err) {
                          console.log(arguments);
                     },
                    '400': function (jqXHR, textStatus, err) {
                        console.log(arguments);
                    }
                }
           })
       })
</script>

2.基於原生js實現

var b2 = document.getElementById("b2");
  b2.onclick = function () {
    // 原生JS
    var xmlHttp = new XMLHttpRequest();
    xmlHttp.open("POST", "/ajax_test/", true);
    xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    xmlHttp.send("username=chao&password=123456");
    xmlHttp.onreadystatechange = function () {
      if (xmlHttp.readyState === 4 && xmlHttp.status === 200) {
        alert(xmlHttp.responseText);
      }
    };
  };

3.Ajax-服務器-Ajax流程圖

三 Ajax請求設置csrf_token

方式1:經過獲取隱藏的input標籤中的csrfmiddlewaretoken值,放置在data中發送。

$.ajax({
  url: "/cookie_ajax/",
  type: "POST",
  data: {
    "username": "anwe",
    "password": 123456,
    "csrfmiddlewaretoken": $("[name = 'csrfmiddlewaretoken']").val()  // 使用jQuery取出csrfmiddlewaretoken的值,拼接到data中
  },
  success: function (data) {
    console.log(data);
  }
})

方式2:

$.ajaxSetup({
    data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});

四 Ajax文件上傳

請求頭ContentType

ContentType指的是請求體的編碼類型,常見的類型共有3種:

1 application/x-www-form-urlencoded

​ 這應該是最多見的 POST 提交數據的方式了。瀏覽器的原生

表單,若是不設置 enctype 屬性,那麼最終就會以 默認格式application/x-www-form-urlencoded 方式提交數據,ajax默認也是這個。請求相似於下面這樣(無關的請求頭在本文中都省略掉了):

Content-Type: application/x-www-form-urlencoded;charset=utf-8

user=anwne&age=22&sex=man   #這就是上面這種contenttype規定的數據格式,後端對應這個格式來解析獲取數據,不論是get方法仍是post方法,都是這樣拼接數據,你們公認的一種數據格式,可是若是你contenttype指定的是urlencoded類型,可是post請求體裏面的數據是下面那種json的格式,那麼就出錯了,服務端無法解開數據。

看network來查看咱們發送的請求體:

點擊一下下面紅框的內容,你就會看到,此次post請求發送數據的原始格式

2 multipart/form-data

​ 這又是一個常見的 POST 數據提交的方式。這種方式通常用來上傳文件,各大服務端語言對它也有着良好的支持。咱們使用表單上傳文件時,必須讓 表單的 enctype 等於 multipart/form-data,form表單不支持發json類型的contenttype格式的數據,而ajax什麼格式均可以發,也是ajax應用普遍的一個緣由。

3 application/json

​ application/json 這個 Content-Type 做爲響應頭你們確定不陌生。實際上,如今愈來愈多的人把它做爲請求頭,用來告訴服務端消息主體是序列化後的 JSON 字符串。因爲 JSON 規範的流行,除了低版本 IE 以外的各大瀏覽器都原生支持 JSON.stringify,服務端語言也都有處理 JSON 的函數,使用 JSON 不會趕上什麼麻煩。

  JSON 格式支持比鍵值對複雜得多的結構化數據,這一點也頗有用。記得之前作過一個項目時,須要提交的數據層次很是深,我就是把數據 JSON 序列化以後來提交的。不過當時我是把 JSON 字符串做爲 val,仍然放在鍵值對裏,以 x-www-form-urlencoded 方式提交。

​ 若是在ajax裏面寫上這個contenttype類型,那麼data參數對應的數據,就不能是個object類型數據了,必須是json字符串,contenttype:'json',簡寫一個json,它也能識別是application/json類型

​ django裏面不能幫咱們解析contenttype值爲json的數據格式,你知道他能幫你解析application/x-www-form-urlencoded 和multipart/form-data(文件上傳會用到)就好了,若是咱們傳json類型的話,須要咱們本身來寫一個解析數據的方法,其實不論是什麼類型,咱們均可以經過原始發送來的數據來進行加工處理,解析出本身想要的數據

基於form表單的文件上傳

<form action="/upload/" method="post" enctype="multipart/form-data">
#上面說的其餘兩種contenttype都是鍵值的形式發送數據,這種form_data的格式通常是把大數據一段一段隔開的
  {% csrf_token %}
  選擇文件:<input type="file" name="head_file">#若是不用form_data格式來發,那麼默認的是urlencoded的格式,這個標籤的數據會組成head_file:文件名字來進行發送
  用戶名:<input type="text" name="username">
  <input type="submit">
</form>

upload.py

def upload(request):
    if request.method == 'GET':
        return render(request,'upload.html')
    else:
        print(request.POST)
        username = request.POST.get('user')
        file_obj = request.FILES.get('file_obj') #得到文件數據對象
        print('>>>',file_obj,type(file_obj))
        #>>> jaden博客.txt <class 'django.core.files.uploadedfile.InMemoryUploadedFile'>,一個文件對象,能夠理解爲一個文件句柄
        file_name = file_obj.name #jaden博客.txt
        print(file_name)
        # 將數據寫到文件裏面,須要名字,須要數據
        with open(file_name,'wb') as f: #直接把文件名字放這裏,那麼文件將直接生成在django的整個項目目錄下,由於django配置的系統搜索的根路徑就是我們的項目文件夾路徑,那個BASE_DIR,通常咱們須要本身創建一個文件夾專門存放上傳的文件
      #因此須要咱們本身來拼接一個路徑放到這裏,os.path.join(settings.BASE_DIR,'media','img',file_name)

            # f.write()  #不能一下寫進去,佔用的內容太多,要一點一點寫
            for data in file_obj: #讀數據
                f.write(data)  #每次讀取的data不是固定長度的,和讀取其餘文件同樣,每次讀一行,識別符爲\r  \n  \r\n,遇到這幾個符號就算是讀了一行
                
            # 寫入文件 固定大小
       for chunks in file_obj.chunks(): #chunks()默認一次返回大小爲經測試爲65536B,也就是64KB,最大爲2.5M,是一個生成器
           f.write(chunks)

基於Ajax的文件上傳

<form>  ##用不用form不要緊,這裏就是個盒子的做用,通常寫form標籤是爲了提示別人,這個地方的內容是要提交的
{% csrf_token %}
    選擇文件:<input type="file" id="head_file">   {#multiple#}
    用戶名:<input type="text" id="username">
    <button id="btn">提交</button>
</form>
<script src="{% static 'js/jquery.js' %}"></script>
<script>
    $('#btn').click(function () {
        var formdata = new FormData(); #ajax上傳文件的時候,須要這個類型,它會將添加給它的鍵值對加工成formdata的類型
        formdata.append('head_file',$('#head_file')[0].files[0]);#添加鍵值的方法是append,注意寫法,鍵和值之間是逗號
        formdata.append('username',$('#username').val());
        formdata.append('csrfmiddlewaretoken',$('[name=csrfmiddlewaretoken]').val());#別忘了csrf_token
        $.ajax({
            url: '/upload/',
            type: 'post',
            data: formdata,#將添加好數據的formdata放到data這裏
            processData:false,
            contentType:false,
            success:function (res) {
                console.log(res)
            }
        })
    })

</script>

upload.py和上面的同樣

JsonResponse

JsonResponse是HttpResponse的子類,專門用來生成JSON編碼的響應。

這個類是HttpRespon的子類,它主要和父類的區別在於:

  • 它的默認Content-Type 被設置爲: application/json
  • 第一個參數,data應該是一個字典類型,當 safe 這個參數被設置爲:False ,那data能夠填入任何能被轉換爲JSON格式的對象,好比list, tuple, set。 默認的safe 參數是 True. 若是你傳入的data數據類型不是字典類型,那麼它就會拋出 TypeError的異常
  • json_dumps_params參數是一個字典,它將調用json.dumps()方法並將字典中的參數傳入給該方法。
from django.http import JsonResponse
def index(request):
    d1 = {'name':'anwen'}

    
    # 一、若是這樣返回,ajax還須要進行json解析
    import json
    return HttpResponse(json.dumps(d1))
    #success:function(res){ var a = JSON.parse(res) }  反序列化

    # 二、使用HttpResponse對象來響應數據的時候,還能夠經過content_type指定格式:
    return HttpResponse(json.dumps(d1),content_type='application/json') 
    #--success:function(res)  {res--自定義對象,不須要本身在反序列化了}
    
    
    # 三、看下面這種,JsonResponse默認就是content_type="application/json"。
    return JsonResponse(d1)

    # 默認只能傳遞字典類型,若是要傳遞非字典類型須要設置一下safe關鍵字參數。
    d1 = [11,22]
    return JsonResponse(d1,safe=False)

def index(request):
    print(request.body)   # 原始的請求體數據
    print(request.GET)    # GET請求數據
    print(request.POST)   # POST請求數據
    print(request.FILES)  # 上傳的文件數據
    return render(request,"index.html")
相關文章
相關標籤/搜索