1. 程式人生 > >第九篇 AJAX

第九篇 AJAX

以及 索引 檢索 list != ret env ddl 常見

AJAX

閱讀目錄(Content)

  • 概述
  • AJAX常見應用情景

    • AJAX的優缺點

  • jQuery實現的AJAX

    • $.ajax參數

  • AJAX請求如何設置csrf_token

  • 序列化

    • Django內置的serializers

  • 補充一個SweetAlert插件示例

概述

對於web應用程序:用戶瀏覽器發送的請求,服務器接收並處理請求,然後返回結果,往往返回就是字符串(HTML),瀏覽器將字符串(HTML)渲染並顯示瀏覽器上。

1.傳統的web應用

一個簡單操作需要重新加載全局數據

2.AJAX

AJAXAsynchronous Javascript And XML)翻譯成中文就是“異步Javascrip和XML”.即使用Javascrip語言與服務器進行異步交互,傳輸的數據為XML(當然,傳輸的數據不只是XML)

  • 同步交互:客戶端發出一個請求後,需要等待服務器響應結束後,才可以發出第二個請求
  • 異步交互:客戶端發出一個請求後,無需等待服務器響應結束後,就可以發出第二個請求
  • 異步的JavaScript: 使用 【JavaScript語言】 以及 相關【瀏覽器提供類庫】 的功能向服務端發送請求,當服務端處理完請求之後,【自動執行某個JavaScript的回調函數】。 PS:以上請求和響應的整個過程是【偷偷】進行的,頁面上無任何感知。
  • XML XML是一種標記語言,是Ajax在和後臺交互時傳輸數據的格式之一

  • 利用AJAX可以做: 1、註冊時,輸入用戶名自動檢測用戶是否已經存在。 2、登陸時,提示用戶名密碼錯誤
    3、刪除數據行時,將行ID發送到後臺,後臺在數據庫中刪除,數據庫刪除成功後,在頁面DOM中將數據行也刪除。(博客園)

小練習:計算兩個數的和

方式一:實現最簡單的

index.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width ,initial-scale=1"
> </head> <body>
#----------------------------------------------------------------
<h1>計算兩個數的和,測試ajax</h1>
<form action="/add/" method="get">
    <input type="text" id="i1" name="i1" value="{{ i1 }}"> +
    <input type="text" id="i2" name="i2" value="{{ i2 }}"> =
    <input type="text" id="ret" name="ret" value="{{ ret }}">
    <input id="b1" type="button" value="發送AJAX請求">
</form>
<script src="/static/jquery-3.2.1.min.js"></script>
<script>
    $(document).ready(function () {
        $(#b1).on(click,function () {
            // 點擊b1標簽要做的事兒
            var i1 = $(#i1).val();
            var i2 = $(#i2).val();
            // 把這兩個數發到後端相加
            $.ajax({
                url:/ajax_add/,
                type:GET,
                data:{i1:i1, i2:i2},
                success:function (arg) {
                    $("#ret").val(arg)
                }
                }
            )

        })
    })
</script>
#-------------------------------------------------------------------- </body> </html>

views.py

from django.shortcuts import render, HttpResponse, redirect

# Create your views here.


def index(request):
    return render(request, index.html)


def ajax_add(request):
    i1 = int(request.GET.get(i1))
    i2 = int(request.GET.get(i2))
    ret = i1 + i2
    return HttpResponse(ret)

技術分享圖片

AJAX常見應用情景

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

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

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

  • 整個過程中頁面沒有刷新,只是刷新頁面中的局部位置而已!
  • 當請求發出後,瀏覽器還可以進行其他操作,無需等待服務器的響應!

技術分享圖片

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

  • 整個過程中頁面沒有刷新,只是局部刷新了;
  • 在請求發出後,瀏覽器不用等待服務器響應結果就可以進行其他操作;

AJAX的優缺點

優點:

  • AJAX使用JavaScript技術向服務器發送異步請求;
  • AJAX請求無須刷新整個頁面;
  • 因為服務器響應內容不再是整個頁面,而是頁面中的部分內容,所以AJAX性能高

jQuery實現的AJAX

技術分享圖片
<!DOCTYPE html>
<html lang="zh-CN">
<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 test</title>
  <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<button id="ajaxTest">AJAX 測試</button>
<script>
  $("#ajaxTest").click(function () {
    $.ajax({
      url: "/text_ajax/",
      type: "POST",
      data: {username: "Q1mi", password: 123456},
      success: function (data) {
        alert(data)
      }
    })
  })
</script>
</body>
</html>
ajax test.html 技術分享圖片
def text_ajax(request):
    if request.method == GET:
        return render(request,text_ajax.html)

    username = request.POST.get(username)
    password = request.POST.get(password)

    print(username, password)
    return HttpResponse("OK")
views.py

$.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

方式1

第一種:通過獲取隱藏的input標簽中的csrfmiddlewaretoken值,放置在data中發送

html

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

views.py

def ajax_login(request):
    if request.method == POST:
        username = request.POST.get(username)
        password = request.POST.get(password)
        # 這塊的username和password對應的是ajax_login.html裏的data裏的數據
        if username == xiao and password == qiang:
        //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
            ret = 登陸成功
        else:
            ret = 用戶名或密碼錯誤
        //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
        return HttpResponse(ret)
    return render(request, ajax_login.html)

======================================================================

html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>ajax_login</title>
    <meta name="viewport" content="width=device-width ,initial-scale=1">
{#    <link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">#}
    <style>
        .error{
            color: red;
        }
    </style>
</head>
<body>
#===========================================================================================================




<form action=""> {% csrf_token %} <p> <label for="username">用戶名</label> <input type="text" id="username" name="username"> <span class="error"></span> </p> <p> <label for="password">密碼</label> <input type="password" id="password" name="password"> <span class="error"></span> </p> <input id="b1" type="button" value="AJAX登錄"> </form> <script src="/static/jquery-3.2.1.min.js"></script> <script> $(#b1).on(click,function () { var username = $(#username).val(); var password = $(#password).val(); // =====獲取CSRF_TOKEN================================== var csrfmiddlewaretokenVal = $(input[name = csrfmiddlewaretoken]).val(); // ================================================== // 發送AJAX請求 $.ajax({ url:/ajax_login/, type:POST, data:{username:username, password:password, csrfmiddlewaretoken:csrfmiddlewaretokenVal}, success:function (arg) { // alert(arg) //=========================================== // JS 中把 JSON 字符串轉換成JS對象 var ret = JSON.parse(arg); //根據後端返回的值,做判斷,如果登陸成功,跳轉 if (ret.status === 1){ location.href=http://www.sogo.com }else{ alert(ret.msg) } } }) })


</script> </body> </html>

views.py

def ajax_login(request):
    if request.method == POST:
        username = request.POST.get(username)
        password = request.POST.get(password)
        # 這塊的username和password對應的是ajax_login.html裏的data裏的數據
        if username == xiao and password == qiang:
        # -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -=
            ret = {status: 1, msg: 登陸成功}
        else:
            ret = {status: 0, msg: 用戶名和密碼錯誤}
        # -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -= -=
        # 字典怎麽轉換成JSON
        json_ret = json.dumps(ret)
        return HttpResponse(json_ret)
    return render(request, ajax_login.html)

方式2

通過獲取返回的cookie中的字符串 放置在請求頭中發送。

註意:需要引入一個jquery.cookie.js插件。

$.ajax({
  url: "/cookie_ajax/",
  type: "POST",
  headers: {"X-CSRFToken": $.cookie(csrftoken)},  // 從Cookie取csrf_token,並設置ajax請求頭
  data: {"username": "Q1mi", "password": 123456},
  success: function (data) {
    console.log(data);
  }
})

或者用自己寫一個getCookie方法:

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);
    }
  }
});

序列化

Django內置的serializers

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)

我們的數據中經常有日期時間,也就是datetime對象,而json.dumps是無法處理這樣在類型的,那就需要通過自定義處理器來做擴展,如下:

class JsonCustomEncoder(json.JSONEncoder):
    """
    自定義一個支持序列化時間格式的類
    """

    def default(self, o):
        if isinstance(o, datetime):
            return o.strftime("%Y-%m-%d %H:%M:%S")
        elif isinstance(o, date):
            return o.strftime("%Y-%m-%d")
        else:
            return json.JSONEncoder.default(self, o)


def books_json(request):
    book_list = models.Book.objects.all().values_list("title", "publish_date")
    ret = json.dumps(list(book_list), cls=JsonCustomEncoder)
    return HttpResponse(ret)

補充一個SweetAlert插件示例

第九篇 AJAX