Python開發之AJAX

1、概述

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

一、傳統的Web應用:一個簡單操做須要從新加載全局數據。html

二、Ajax前端

AJAX,Asynchronous JavaScript and XML (異步的JavaScript和XML),一種建立交互式網頁應用的網頁開發技術方案。
 
異步的JavaScript:
    使用 【JavaScript語言】 以及 相關【瀏覽器提供類庫】 的功能向服務端發送請求,當服務端處理完請求以後,【自動執行某個JavaScript的回調函數】。
PS:以上請求和響應的整個過程是【偷偷】進行的,頁面上無任何感知。
XML
    XML是一種標記語言,是Ajax在和後臺交互時傳輸數據的格式之一
PS:
XML 通常用於編寫配置文件,語法方便描述配置文件內的信息,舉例以下:
<start>  
    <username>xiaowang</username>
    <age>18</age>
       .....
</start>
 
利用AJAX能夠作:
一、註冊時,輸入用戶名自動檢測用戶是否已經存在。
二、登錄時,提示用戶名密碼錯誤
三、刪除數據行時,將行ID發送到後臺,後臺在數據庫中刪除,數據庫刪除成功後,在頁面DOM中將數據行也刪除。(博客園)

三、Ajax分類及定義java

Ajax操做共分爲三類:原生Ajax,jQuery Ajax,和僞Ajax 三種方式。這三種方法都能偷偷向後臺發送請求。目前熟知的僅是 jquery ajax。jquery

1. 原生ajax:是ajax本質,經過頁面的XMLHttpRequest對象來調用。send 發送數據,往請求體裏放數據。
2. jquery與ajax的關係 內部基於"原生ajax" 是對原生ajax的封裝,使用起來簡單。
  jquery 至關因而個模塊,他調用了不少內置方法,把發送ajax請求的方法,封裝在了其內部,咱們使用的時候直接調用ajax這個函數便可。
3. 僞ajax,不用XMLHttpRequest對象,使用瀏覽器裏的標籤和標籤的特性僞造出來的。ajax

2、原生Ajax

  Ajax主要就是使用 【XmlHttpRequest】對象來完成請求的操做,該對象在主流瀏覽器中均存在(除早期的IE),Ajax首次出現IE5.5中存在(ActiveX控件)。數據庫

XmlHttpRequest對象介紹

a. void open(String method,String url,Boolen async)
   用於建立請求
     
   參數:
       method: 請求方式(字符串類型),如:POST、GET、DELETE...
       url:    要請求的地址(字符串類型)
       async:  是否異步(布爾類型)
  
b. void send(String body)
    用於發送請求
  
    參數:
        body: 要發送的數據(字符串類型)
  
c. void setRequestHeader(String header,String value)
    用於設置請求頭
  
    參數:
        header: 請求頭的key(字符串類型)
        vlaue:  請求頭的value(字符串類型)
  
d. String getAllResponseHeaders()
    獲取全部響應頭
  
    返回值:
        響應頭數據(字符串類型)
  
e. String getResponseHeader(String header)
    獲取響應頭中指定header的值
  
    參數:
        header: 響應頭的key(字符串類型)
  
    返回值:
        響應頭中指定的header對應的值
  
f. void abort()
  
    終止請求

二、XmlHttpRequest對象的主要屬性:django

a. Number readyState
   狀態值(整數)
  
   詳細:
      0-未初始化,還沒有調用open()方法;
      1-啓動,調用了open()方法,未調用send()方法;
      2-發送,已經調用了send()方法,未接收到響應;
      3-接收,已經接收到部分響應數據;
      4-完成,已經接收到所有響應數據;
  
b. Function onreadystatechange
   當readyState的值改變時自動觸發執行其對應的函數(回調函數)
  
c. String responseText
   服務器返回的數據(字符串類型)
  
d. XmlDocument responseXML
   服務器返回的數據(Xml對象)
  
e. Number states
   狀態碼(整數),如:200、404...
  
f. String statesText
   狀態文本(字符串),如:OK、NotFound...
 function func1() {
        var xmlhttp = createHMLHttpRequeset();
        xmlhttp.open("POST", "/ajax_recevie/", true) //請求的監控的地址
        xmlhttp.send("name-NBA")
        xmlhttp.onreadystatechange = function () {
            if (xmlhttp.readyState == 4 /*&& xmlhttp.status==200*/) {
                var data = xmlhttp.responseText
                alert(data)
            };
        }
    }
     function  createHMLHttpRequeset() {
       //建立一個XMLHttpRequest,try防止瀏覽器不一致形成建立不成功
      /* var xmlHttp;
       try {
           xmlHttp=new  XMLHttpRequest();
       }catch (e){
           try{
               xmlHttp =new  ActiveXObject("Msxml2.XMLHTTP");
           }catch (e){
               try {
                   xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
               }catch (e){}
           }
       }
       return xmlHttp;*/
      var xmlHttp;
      xmlHttp=new  XMLHttpRequest();
      return xmlHttp
     }
建立一個XmlHttpRequest請求

三、跨瀏覽器支持json

XmlHttpRequest
  IE7+, Firefox, Chrome, Opera, etc.後端

ActiveXObject("Microsoft.XMLHTTP")

  IE6, IE5

3、jQuery Ajax

jQuery其實就是一個JavaScript的類庫,其將複雜的功能作了上層封裝,使得開發者能夠在其基礎上寫更少的代碼實現更多的功能。

    jQuery 不是生產者,而是原生ajax的搬運工。

    jQuery Ajax本質 XMLHttpRequest 或 ActiveXObject 

jQuery.get(...)
                全部參數:
                     url: 待載入頁面的URL地址
                    data: 待發送 Key/value 參數。
                 success: 載入成功時回調函數。
                dataType: 返回內容格式,xml, json,  script, text, html


            jQuery.post(...)
                全部參數:
                     url: 待載入頁面的URL地址
                    data: 待發送 Key/value 參數
                 success: 載入成功時回調函數
                dataType: 返回內容格式,xml, json,  script, text, html


            jQuery.getJSON(...)
                全部參數:
                     url: 待載入頁面的URL地址
                    data: 待發送 Key/value 參數。
                 success: 載入成功時回調函數。


            jQuery.getScript(...)
                全部參數:
                     url: 待載入頁面的URL地址
                    data: 待發送 Key/value 參數。
                 success: 載入成功時回調函數。


            jQuery.ajax(...)

                部分參數:

                        url:請求地址
                       type:請求方式,GET、POST(1.9.0以後用method)
                    headers:請求頭
                       data:要發送的數據
                contentType:即將發送信息至服務器的內容編碼類型(默認: "application/x-www-form-urlencoded; charset=UTF-8")
                      async:是否異步
                    timeout:設置請求超時時間(毫秒)
                    traditional: true,// 若是提交的數據的值有列表,則須要添加此屬性,讓數據不作轉換。
                 beforeSend:發送請求前執行的函數(全局)
                   complete:完成以後執行的回調函數(全局)
                    success:成功以後執行的回調函數(全局)
                      error:失敗以後執行的回調函數(全局)
                

                    accepts:經過請求頭髮送給服務器,告訴服務器當前客戶端課接受的數據類型
                   dataType:將服務器端返回的數據轉換成指定類型
                                   "xml": 將服務器端返回的內容轉換成xml格式
                                  "text": 將服務器端返回的內容轉換成普通文本格式
                                  "html": 將服務器端返回的內容轉換成普通文本格式,在插入DOM中時,若是包含JavaScript標籤,則會嘗試去執行。
                                "script": 嘗試將返回值看成JavaScript去執行,而後再將服務器端返回的內容轉換成普通文本格式
                                  "json": 將服務器端返回的內容轉換成相應的JavaScript對象
                                 "jsonp": JSONP 格式
                                          使用 JSONP 形式調用函數時,如 "myurl?callback=?" jQuery 將自動替換 ? 爲正確的函數名,以執行回調函數

                                  若是不指定,jQuery 將自動根據HTTP包MIME信息返回相應類型(an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string

                 converters: 轉換器,將服務器端的內容根據指定的dataType轉換類型,並傳值給success回調函數
                         $.ajax({
                              accepts: {
                                mycustomtype: 'application/x-some-custom-type'
                              },
                              
                              // Expect a `mycustomtype` back from server
                              dataType: 'mycustomtype'

                              // Instructions for how to deserialize a `mycustomtype`
                              converters: {
                                'text mycustomtype': function(result) {
                                  // Do Stuff
                                  return newresult;
                                }
                              },
                            });
jQuery Ajax方法列表

原生Ajax及jQuery Ajax使用示例:

- index.html頁面設置兩種方法,方便於比較

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/static/js/jquery-3.2.1.js"></script>
</head>
<body>
<input type="text" id ="i1">
+
<input type="text" id="i2">
=
<input type="text" id="es">
<p>
    <input type="button" id="btn1" value="提交" onclick="add1();">
    <input type="button" id="btn2" value="原生提交" onclick="add2();">
</p>
<script>
    function add1() {
        $.ajax({
            url:"/add1/",
            type:"POST",
            data:{"i1":$("#i1"),"i2":$("#i2")},
            success:function (arg) {
                $("#es").val(arg);
            }
        })
    }
    function add2() {
        var xhr = new XMLHttpRequest();
{#        只要狀態發生變化,就會立馬被執行#}
        xhr.onreadystatechange = function () {
            if (xhr.readyState==4){
                alert(xhr.responseText);
            } {# 回調函數,接收到從服務端返回的數據進行處理 #}
        };
{#        GET方式提交,數據放在url中#}
{#        xhr.open("GET","/add2/?i1=10&i2=18");#}
{#        xhr.send();#}
{#        POST方式提交#}
        xhr.open("POST","/add2/");  {# 打開鏈接 #}
{#        注意POST請求的時候,要設置請求頭信息,不然後臺POST格式拿不到數據#}
        xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
        xhr.send("i1=12&i2=19");  {# 發送數據 #}
    }
</script>
</body>
</html>
Vindex.html頁面

-views.py 視圖函數中的操做

from django.shortcuts import render,HttpResponse
import os
# Create your views here.

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

def add1(request):
    a1 = int(request.POST.get("i1"))
    a2 = int(request.POST.get("i2"))
    return HttpResponse(str(a1+a2))

def add2(request):
    if request.method == "GET":
        i1 = int(request.GET.get("i1"))
        i2 = int(request.GET.get("i2"))
        print("add2……")
        return HttpResponse(i1+i2)
    else:
        print(request.POST)
        i1 = int(request.POST.get("i1"))
        i2 = int(request.POST.get("i2"))
        print(request.body)
        print("add2……POST")
        return HttpResponse(i1+i2)
Views.py後臺處理方式

4、僞 Ajax

  因爲HTML標籤的iframe標籤具備局部加載內容的特性,因此可使用其來僞造Ajax請求。

一、iframe 標籤:

標籤特性:在當前頁面不刷新的狀況下,在本標籤的框內,徹底加載其餘頁面。

原理:src指定一個url地址,在當前頁面不刷新的狀況下,直接把對應的整個網頁中全部的代碼加載到iframe標籤中。

- 示例:

  在頁面直接查看其餘網頁,同時本身手動輸入網址,也能夠查看對應頁面。

- autohome.html頁面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div>
<input type="text" id="txt1">
<input type="button" value="查看" onclick="changeScr();">
</div>
<iframe id="ifr" src="http://www.autohome.com.cn"></iframe>
<script>
    function changeScr() {
        var inp = document.getElementById("txt1").value;
        document.getElementById("ifr").src = inp
    }
</script>
</body>
</html>
頁面顯示

- views.py後臺處理方式:

後臺處理方式

注意點:

  一、iframe標籤內是整個頁面全拿到,沒錯就是全部的標籤和內容!至關於把另外一個頁面copy到它標籤下。iframe能夠實如今本身的標籤內部刷新,整個頁面不刷新而是局部刷新。具備不刷新就能打開頁面的效果。
  二、iframe標籤,具備不刷新頁面能發送http請求,打開相對應頁面的功能,當前頁面從新加載也不會發生改變。

基於這種方式,咱們就想到利用iframe標籤的特性和form表單標籤具備提交數據的功能結合,僞造日後臺提交數據的方法:

  iframe標籤與form標籤結合,把form表單內全部的數據交給iframe標籤,由iframe標籤提交給後臺服務端。form表單中一條屬性target與iframe標籤的name創建聯繫(target屬性值與name值一致),從而實現頁面不刷新,偷偷日後臺發送數據的目的。

基於iframe標籤和Form表單實現僞ajax操做

注意點:頁面嵌套頁面須要經過特定的方法去尋找。得進入文本里邊去拿對應的文本內容。

代碼示例:

- 網頁代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form id="f1" method="POST" action="/fake_ajax/" target="ifr">
    <iframe id="ifr" name="ifr" frameborder="1"></iframe>
    <input type="text" name="user">
    <a onclick="submitForm();">提交</a>
</form>
<script>
    function submitForm() {
        document.getElementById("ifr").onload = loadIframe;
        document.getElementById("f1").submit();
    }
    function loadIframe() {
{#        alert(123);#}
        var content = document.getElementById("ifr").contentWindow.document.body.innerText;
        console.log(content);
    }
</script>
</body>
</html>
僞ajax方式提交之頁面

- views.py 後臺處理

def fake_ajax(request):
    if request.method=="GET":
        return render(request,"fake_ajax.html")
    else:
        print(request.POST)
        print(request.POST.get("user"))
        return HttpResponse(request.POST.get("user"))
後臺處理

關於解決頁面加載,函數未定義的問題:
  html標籤中設置一個提交按鈕,這個按鈕綁定一個點擊事件,這個事件在JS代碼中對應一個函數,該函數內部存在一個加載完成以後的綁定加載方法,這個方法再對應另外一個函數。這樣就能解決頁面加載函數未定義的問題。
js代碼中,經過找到form標籤也能夠完成提交的操做     DOM對象.submit()

基於ajax上傳文件(POST)方式提交,並在當前頁面預覽

一、原生ajax
  如今的主流瀏覽器都有一個FormData方法,基於formData對象,這個對象能夠傳文件也能夠傳字符串。
  獲取文件對象:經過input 便籤 type=files 的文件標籤對象.files[0]
  先在本地上傳完文件,再把該文件保存的地址返回給瀏覽器,頁面動態建立一個img標籤,src ="服務端返回的文件路徑"(注意文件路徑的格式<'/'開頭>須要拼接!!)。 用於文件的預覽(主要是圖片)。
二、jquery ajax
  注意也是構造內容對象,和傳值 data = FormData對象。
  傳輸文件注意,須要添加兩條屬性,告訴jquery再也不作數據的處理。
    contentType:false,
    processData:false,

弊端:原生ajax和jQuery Ajax兩種方式,依賴FormData這個對象這就直接致使兼容性較差,主要是出來的時間太晚。

三、僞ajax
  相比上邊兩種操做,因爲僞Ajax是由兩個標籤來完成數據提交操做的,而不是用插件,因此幾乎全部的瀏覽器都支持。上傳文件首選。

  使用form表單上傳文件,注意添加enctype屬性。
  注意從iframe標籤中拿數據的方式,及從新加載的方式。

文件提交示例:

- 上傳頁面及script操做:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/static/js/jquery-3.2.1.js"></script>
</head>
<body>
    <h1>原生Ajax上傳文件</h1>
    <input type="file" id="i1">
    <a onclick="upload1()">上傳</a>
    <div id="container1"></div>  {# 用於預覽圖片 #}

    <h1>jQuery Ajax上傳文件</h1>
    <input type="file" id="i2">
    <a onclick="upload2()">上傳</a>
    <div id="container2"></div>  {# 用於預覽圖片 #}

    <h1>僞Ajax上傳文件</h1>
    <form id="f1" method="POST" action="/upload/" target="ifr" enctype="multipart/form-data">
        <iframe id="ifr" name="ifr" style=""></iframe>
        <input type="file" name="files"/>
        <a onclick="upload3();">上傳</a>
    </form>
    <div id="c3"></div>

    <script>
        function upload1() {
            var formData = new FormData();{# 經過FormData對象獲取文件或字符串信息 #}
            formData.append("k1","v1");
            formData.append("files",document.getElementById("i1").files[0]);
            console.log(document.getElementById("i1"));
            console.log(document.getElementById("i1").files);
            console.log(document.getElementById("i1").files[0]);
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4){
                    var file_path = xhr.responseText;
                    var tag = document.createElement("img");
                    tag.src = "/"+file_path;
                    document.getElementById("container1").appendChild(tag);
                }
            };
            xhr.open("POST","/upload/");
            xhr.send(formData);
        }
        function upload2() {
            var formData = new FormData();
            formData.append("k1","v1");
            formData.append("files",$("#i2")[0].files[0]);
            $.ajax({
                url: "/upload/",
                type:"POST",
                data:formData,
                contentType:false,
                processData:false,
                success:function (arg) {
                    var tag = document.createElement("img");
                    tag.src="/"+arg;
                    $("#container2").append(tag);
                }
            })
        }
        function upload3() {
            document.getElementById("ifr").onload=loadIframes;
            document.getElementById("f1").submit();
        }
        function loadIframes() {
            var content = document.getElementById("ifr").contentWindow.document.body.innerText;{#在iframe標籤中獲取返回的數據#}
            var tags = document.createElement("img");
            tags.src = "/" + content;
            document.getElementById("c3").appendChild(tags);
        }
    </script>
</body>
</html>
upload.html

- 後臺對請求處理操做:

def upload(request):
    if request.method =="GET":
        return render(request,"upload.html")
    else:
        print(request.POST,request.FILES)
        file_obj = request.FILES.get("files")
        file_path = os.path.join("static",file_obj.name)
        with open(file_path,"wb") as f:
            for chunk in file_obj.chunks():
                f.write(chunk)
        return HttpResponse(file_path)
Views.py 後臺操做

關於上傳文件按鈕假裝:

  任何一個頁面原生的按鈕都是醜陋了,爲了好看都須要作一層假裝。在一個框內寫上兩個標籤,一個input標籤,另外一個自定義,而後設置優先級,把input的優先級調低而且透明度爲0。顯示出好看的標籤。

以上三種提交數據總結:

記住一句話:根據使用狀況而定使用哪一種方式提交數據。

一、如果實現上傳文件的功能,那首選 僞ajax,緣由及就一點:兼容性強!

二、如果實現傳輸普通文本數據的功能,須要在兩個層面上考慮,一個是代碼的書寫難度,一個是性能;固然推薦使用jquery,由於簡單,可是須要導入一個300k左右的功能包;如果大公司,對性能上或是訪問量大的網站寫這種操做的話,就要首先考慮用原生ajax或是僞ajax,這兩種方法都是用幾行代碼去實現功能,不須要事先導入先導入一個模塊。

5、跨域Ajax

因爲瀏覽器存在同源策略機制,同源策略阻止從一個源加載的文檔或腳本獲取或設置另外一個源加載的文檔的屬性。

特別的:因爲同源策略是瀏覽器的限制,因此請求的發送和響應是能夠進行,只不過瀏覽器不接受罷了。

瀏覽器同源策略並非對全部的請求均制約:

  • 制約: XmlHttpRequest,
  • 不叼: img、iframe、script等具備src屬性的標籤

跨域,跨域名訪問,如:http://www.c1.com 域名向 http://www.c2.com域名發送請求。

JSONP實現跨域請求

  JSONP(JSONP - JSON with Padding是JSON的一種「使用模式」),利用script標籤的src屬性(瀏覽器容許script標籤跨域)

JSONP    ------>注意一點:發送的是GET請求
    是一種技巧或是說技術,
    Ajax存在一個問題:訪問本身域名URL的請求是沒有任何問題的,可是訪問其餘域名URL的時候,瀏覽器會作出相應的操做,請求就會被阻止。
產生緣由:
    瀏覽器在當前頁面給第三方發送請求,數據也從服務器發會給瀏覽器,可是因爲瀏覽器的同源策略,數據被瀏覽器禁止了,返回值就接收不到。
    因爲這種緣由,瀏覽器斷定只能給當前的url發送請求,不能跨域。
    瀏覽器:同源策略
        - 禁止:Ajax跨域發送請求時,再回來時瀏覽器拒絕接收。
        - 容許:img,script標籤沒禁止  瀏覽器不會阻止src=""的加載。
     
處理方法:繞過瀏覽器的同源策略(鑽空子),既然禁止ajax跨域,可是容許帶有src屬性標籤進行跨域。
因此就再也不用ajax去發送請求而是建立一個有這種屬性的標籤,而後把跨域請求的url寫到src屬性下,而後把這個帶有數據的標籤加到當前頁面上。
例如利用script便籤,而後請求返回的內容就會交給script進行解析。
 
利用src發送請求,就會把訪問的頁面內容徹底下載下來,保存在內存當中。如果有對應的加載策略,頁面一刷新就能把型對應的數據在頁面上顯示出來。
     
    JSONP:鑽空子
        # http://www.baidu.com?p=1&name=xx
        0. function list(arg){
            console.log(arg);
          }
         
        1. 發送:把url地址放在標籤中
            把數據拼接成,script放在html
            <script src='http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403'></script>
            返回的是list({......})函數,當前頁面也得有一個相對應的調用函數,數據一返回就能執行這個調用的函數,把數據加載顯示出來。
        要求:遠程返回值必須是一個有參數的函數,在當前本地執行這個函數就能獲取到數據,因此咱們都須要遵照這個規則。
         
        利用js 能夠被瀏覽器加載的特性。
        看成js代碼放到瀏覽器所屬客戶端的內存中   
跨域請求,獲取其餘網站的數據方法:
    第一種:瀏覽器向本身服務端發送請求,獲取到數據以後,再向其餘網站的服務端發送請求,接收該服務端的返回的數據。這種方式須要考慮同源策略的問題。
    第二種:瀏覽器向本身的服務端發送請求,而後服務端再向要其餘的服務端發送請求,獲取到數據,再把數據傳遞給瀏覽器。這種方式就不用考慮同源策略,也不會用到JSONP跨域操做了。
    注意:服務端不是瀏覽器,訪問任意網站發送請求,都會拿到返回的數據。
 
開發需求:向其餘網站發Http請求  
    - 瀏覽器直接發送請求【考慮同源】
    - 瀏覽器->服務端->發送請求     
API:別人給提供的路徑或是方法,經過這個方法就能獲取到對應的數據。
 
瀏覽器直接發送請求【考慮同源】
注意:同源策略是瀏覽器作的策略,只要瀏覽器發送請求,服務端就會把數據返回給客戶端存放於內存中,能不能渲染仍是瀏覽器說了算。  
    要求:客戶端和服務端協議必須達成一致,才能夠實現跨域請求的操做!
        1. 客戶端
            - URL?callback=xxxx   服務端以GET形式發送請求,把函數名放在url中
            - function xxxx(arg){}  定義一個針對這個請求的自執行函數,用於加載後臺返回的數據。
                 
        2. 服務端
            - 獲取 funcname = request.GET.get(callback) 獲取GET請求 url 中自定義的函數名
            - 返回: funcname(....)   以一個函數帶數據的形式返回給瀏覽器
     
    Jquery內部已經封裝了JSONP的方法,因此須要跨域的話,jquery內部也能實現操做,直接就使用jquery的對應方法便可。
    JSONP編寫模版:
        後臺發送返回的數據,作成一個可操做的對象返回。瀏覽器前端接收到數據,而後利用js加載顯示獲取數據。
 
    注意:
        變量名要在瀏覽器中本身定義或命名,後臺不用管直接對數據拼接操做就行,而後返回給瀏覽器。
        瀏覽器要自定義一個函數執行這個操做,只要後臺把數據返回,就自動執行對應的函數,把數據顯示。
     
    使用:分爲兩種方式:
        1. 本身動態建立script標籤,src添加url地址,定製加載函數。
            function getUsers(){
                 var tag = document.createElement('script');
                tag.src = "http://www.s4.com:8001/users/?funcname=bbb?sdd";
                document.head.appendChild(tag);
             }
        2. 直接利用jQuery ajax請求實現跨域操做,也須要自定義加載函數。
            $.ajax({
                url: 'http://www.s4.com:8001/users/',  跨域要訪問的地址
                type: 'GET',                           請求方式,必須是GET   換成了其餘方式也會以GET方式請求。
                dataType: 'JSONP',                     指定參數,規定那種方法操做發送數據
                jsonp: 'funcname',                     GET請求名
                jsonpCallback: 'bbb'                   GET請求發送給後端的值
            })
    jquery ajax以JSONP技術向後臺發送GET請求,上段代碼會內部處理拼接成一個新的url地址,即:http://www.s4.com:8001/users/?funcname=bbb 發給服務端。
         
    總結:
    難點:怎麼從內存中拿取返回的數據。因此須要按照必定的規則來傳遞數據。
    注意點:
        - 瀏覽器只能發GET請求
        - 瀏覽器與服務端之間必須約定好方法。參數必定是動態的!!!
    JSONP是一種方式,目的解決跨域問題。每一種語言中都有。
JSONP

JSONP(JSONP - JSON with Padding是JSON的一種「使用模式」),利用script標籤的src屬性(瀏覽器容許script標籤跨域)

除JSONP外其餘的跨域操做!修改配置,讓瀏覽器的同源策略失效,全部的瀏覽器訪問都能接收到數據。

<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>

    <p>
        <input type="button" onclick="Jsonp1();"  value='提交'/>
    </p>

    <p>
        <input type="button" onclick="Jsonp2();" value='提交'/>
    </p>

    <script type="text/javascript" src="jquery-1.12.4.js"></script>
    <script>
        function Jsonp1(){
            var tag = document.createElement('script');
            tag.src = "http://c2.com:8000/test/";
            document.head.appendChild(tag);
            document.head.removeChild(tag);

        }

        function Jsonp2(){
            $.ajax({
                url: "http://c2.com:8000/test/",
                type: 'GET',
                dataType: 'JSONP',
                success: function(data, statusText, xmlHttpRequest){
                    console.log(data);
                }
            })
        }


    </script>
</body>
</html>
JSONP實現跨域請求

CORS

隨着技術的發展,如今的瀏覽器能夠支持主動設置從而容許跨域請求,即:跨域資源共享(CORS,Cross-Origin Resource Sharing),其本質是設置響應頭,至關因而通行證,使得瀏覽器容許跨域請求。

CORS --->自認爲是高端操做:跨域資源共享  返回數據在響應頭中加值,讓瀏覽器放棄同源策略不在阻止。
     
隨着技術的發展,如今的瀏覽器能夠支持主動設置從而容許跨域請求,即:跨域資源共享(CORS,Cross-Origin Resource Sharing),
其本質是設置響應頭,至關因而通行證,使得瀏覽器容許跨域請求。
 
    內部存在機制,判斷是什麼請求,如果簡單請求直接把數據返回。複雜的請求,會發兩次請求,第一次是自動發送的預檢請求option,發送的內容沒有數據,
後臺預檢完畢,纔會再發送帶數據的操做請求。
     
    簡單請求:
         
        def new_users(request):
            obj = HttpResponse('返回內容')
            obj['Access-Control-Allow-Origin'] = "*" 
                #設置容許跨域操做的響應頭,值爲容許訪問的url地址。*表明所有。
            return obj
     
    複雜請求:
        兩次請求:
        第一次:自動發送預檢請求,沒有數據,後臺作檢測允不容許這個操做。
        第二次:容許就發送帶數據的請求操做。
        def new_users(request):
 
            if request.method == "OPTIONS":
                obj = HttpResponse()
                obj['Access-Control-Allow-Origin'] = "*"
                obj['Access-Control-Allow-Methods'] = "DELETE"
                return obj
 
            obj = HttpResponse('asdfasdf')
            obj['Access-Control-Allow-Origin'] = "*"
            return obj
    注意點:兩次請求,都須要瀏覽器容許該操做!即須要添加響應頭信息。
    其餘:
        - 任何請求
        詳情參見 老司機博客  http://www.cnblogs.com/wupeiqi/articles/5703697.html
CORS

練習 

JSONP跨域請求示例,代碼以下:

s4day79項目:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="/static/js/jquery-3.2.1.js"></script>
</head>
<body>
<input type="button" value="獲取用戶列表" onclick="getUsers();">
<ul id="user_List">
    
</ul>
<script>

    //生成一個script標籤,src是要請求的地址,進行跨域操做
{#    function getUsers() {#}
{#        var tag = document.createElement("script");#}
{#        tag.src = "http://www.s4day80.com:8001/users/?funcname=bbb";#}
{#        document.head.appendChild(tag);#}
{#    }#}
    //數據返回後,自動執行自定義的函數,從內存中獲取返回的數據
{#    function bbb(arg) {#}
{#        console.log(arg);#}
{#    }#}
    //ajax發送跨域請求操做
    function getUsers() {
        // XMLHttpRequest ----->ajax發送請求,瀏覽器同源策略直接阻止。
{#        $.ajax({#}
{#            url: 'http://www.s4day80.com:8001/users/?funcname=bbb',#}
{#            type: 'GET',#}
{#            success: function (arg) {#}
{#                console.log(arg);#}
{#            }#}
{#        });#}

        // JSONP    給請求打上JSONP的標籤,這樣就不會被阻止。
        $.ajax({
            url: 'http://www.s4.com:8001/users/',
            type: 'POST',
            dataType: 'JSONP',
            jsonp: 'funcname',
            jsonpCallback: 'bbb'
        })
    }
    //同上
    function bbb(arg){
        console.log(arg);
    }
    
</script>
</body>
</html>
JSONP.html
def jsonp(request):
    return render(request,"jsonp.html")
views.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^jsonp/', views.jsonp),

]
url.py

s4day80項目下:

import json
from django.shortcuts import render,HttpResponse

def users(request):
    v = request.GET.get("funcname")
    print("請求來了....")
    user_list = ["alex","eric","egon"]
    user_list_str = json.dumps(user_list,)
    temp = "%s(%s)"%(v,user_list_str,)
    print(temp,type(temp))
    return HttpResponse(temp)
vires.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^users/', views.users),
]
url.py

CORS跨域資源共享,示例代碼:

s4day79項目:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <input type="button" value="獲取用戶列表" onclick="getUsers();" />
    <ul id="user_list">

    </ul>
    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function getUsers(){
            $.ajax({
                url: 'http://www.s4.com:8001/new_users/',
                type:"DELETE",
                success:function(arg){
                    console.log(arg);
                }
            })
        }
    </script>
</body>
</html>
cors.html
def cors(request):
    return render(request,'cors.html')
views.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),

    url(r'^cors/', views.cors),
]
url.py

s4day80項目下:

def new_users(request):
    print(request.method)

    #簡單的跨域請求
    # user_list = [
    #     'alex','eric','egon'
    # ]
    # user_list_str = json.dumps(user_list)
    # obj = HttpResponse(user_list_str)
    #
    # obj['Access-Control-Allow-Origin'] = "*"
    # return obj

    #複雜跨域請求
    if request.method == "OPTIONS":
        obj = HttpResponse()
        obj['Access-Control-Allow-Origin'] = "*"
        obj['Access-Control-Allow-Methods'] = "DELETE"
        return obj
    obj = HttpResponse('asdfasdf')
    obj['Access-Control-Allow-Origin'] = "*"
    return obj
views.py
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),

    url(r'^new_users/', views.new_users),
]
url.py

 jQuery ajax()使用serialize()提交form數據

相關文章
相關標籤/搜索