Python開發之AJAX全套

概述

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

一、傳統的Web應用python

一個簡單操做須要從新加載全局數據

二、AJAXjquery

AJAX,Asynchronous JavaScript and XML (異步的JavaScript和XML),一種建立交互式網頁應用的網頁開發技術方案。

異步的JavaScript:
使用 【JavaScript語言】 以及 相關【瀏覽器提供類庫】 的功能向服務端發送請求,當服務端處理完請求以後,【自動執行某個JavaScript的回調函數】。
PS:以上請求和響應的整個過程是【偷偷】進行的,頁面上無任何感知。
XML
XML是一種標記語言,是Ajax在和後臺交互時傳輸數據的格式之一
利用AJAX能夠作:
一、註冊時,輸入用戶名自動檢測用戶是否已經存在。
二、登錄時,提示用戶名密碼錯誤
三、刪除數據行時,將行ID發送到後臺,後臺在數據庫中刪除,數據庫刪除成功後,在頁面DOM中將數據行也刪除。

示例:經過ajax發送數據ajax

 

urls.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'^index.html$', views.index),
    url(r'^ajax1.html$', views.ajax1),

]

settings.pydjango

#注掉csrfjson

STATIC_URL = '/static/'
STATICFILES_DIRS = (
        os.path.join(BASE_DIR,'static'),
)

views.py跨域

from django.shortcuts import render
from django.shortcuts import HttpResponse
from app01 import models
# Create your views here.


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

def ajax1(request):
    print(request.GET)
    print(request.POST)
    return HttpResponse('ok')

index.html瀏覽器

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

    <style>
        .bin{
           display: inline-block;
            padding:5px 10px;
            background-color:coral;
            color: white;
        }
    </style>

</head>
<body>
    <h1>Ajax全套</h1>
    <h3>jQery Ajax</h3>
    <div>
        <a class="bin onclick=AjaxSubmitl();">點我</a>
    </div>

    <script src="/static/js/jquery-3.1.1.js"></script>
    <script>
        function AjaxSubmitl() {
            $.ajax({
                url:'/ajax1.html',
                type:'GET',
                data:{'p':123},
                success:function(arg){

                }
            })
        }

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

原生AJAX

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

一、XmlHttpRequest對象介紹

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對象的主要屬性:

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

 

示例:經過原生XmlHttpRequest對象發送

urls.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'^ajax1.html$', views.ajax1),

]

views.py

from django.shortcuts import render
from django.shortcuts import HttpResponse
from app01 import models
# Create your views here.


def ajax1(request):
    print(request.GET)
    print(request.POST)
    return HttpResponse('ok')

index.html

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

    <style>
        .bin{
           display: inline-block;
            padding:5px 10px;
            background-color:coral;
            color: white;
        }
    </style>

</head>
<body>
    <h1>Ajax全套</h1>
    <h3>jQery Ajax</h3>
    <div>
        <a class="bin onclick=AjaxSubmit2();">點我</a>
    </div>

    <script src="/static/js/jquery-3.1.1.js"></script>
    <script>

        function AjaxSubmit2() {
            $.ajax({
                url:'/ajax1.html',
                type:'GET',
                data:{'p':123},
                success:function(arg){
                }
            })
        }

        function AjaxSubmit2() {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if(xhr.readyState ==4 ){
                    //接收完畢服務器返回的數據
                    console.log(xhr.responseText);

                }
            };
            xhr.open('GET','/ajax1.html?p=123');
            xhr.send(null);
        }

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

 示例2:

 urls.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'^index.html$', views.index),
    url(r'^ajax1.html$', views.ajax1),
]

views.py

from django.shortcuts import render
from django.shortcuts import HttpResponse
from app01 import models
# Create your views here.


def index(request):

    return render(request,'index.html')

def ajax1(request):
    print(request.GET)
    print(request.POST)
    print(request.body)
    return HttpResponse('ok')

index.html

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

    <style>
        .bin {
            display: inline-block;
            padding: 5px 10px;
            background-color: coral;
            color: white;
        }
    </style>

</head>
<body>
<h1>Ajax全套</h1>
<h3>一、Ajax發送GET請求</h3>
<div>
    <a class="bin onclick=AjaxSubmit1();">點我</a>
    <a class="bin onclick=AjaxSubmit2();">點我</a>
</div>

<h3>二、Ajax發送POST請求</h3>
<div>
    <a class="bin onclick=AjaxSubmit3();">點我</a>
    <a class="bin onclick=AjaxSubmit4();">點我</a>
</div>

{#<h3>三、莆田</h3>#}
{#<div>#}
{#    <h6>學習iframe</h6>#}
{#    <div>#}
{#    <input id="url" placeholder="請輸入url" /><a onclick="Test1();">查看</a>#}
{#    </div>#}
{#    <iframe id="iframe" style="height: 800px; width: 600px;" src="http://www.autohome.com.cn"></iframe>#}
{#</div>#}

<script src="/static/js/jquery-3.1.1.js"></script>
<script>

    function AjaxSubmit1() {
        $.ajax({
            url: '/index.html',
            type: 'GET',
            data: {'p': 123},
            success: function (arg) {
            }
        })
    }

    function AjaxSubmit2() {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                //接收完畢服務器返回的數據
                console.log(xhr.responseText);

            }
        };
        xhr.open('GET', '/ajax1.html?p=123');
        xhr.send(null);
    }

    function AjaxSubmit3() {
        $.ajax({
            url: '/ajax1.html',
            type: 'POST',
            data: {'p': 123},
            success: function (arg) {
            }
        })
    }

    function AjaxSubmit4() {
        var xhr = new XMLHttpRequest();
        xhr.onreadystatechange = function () {
            if (xhr.readyState == 4) {
                //接收完畢服務器返回的數據
                console.log(xhr.responseText);

            }
        };
        xhr.open('POST', '/ajax1.html');
        {# 設置請求頭,發送post請求的時候,記得帶請求頭vlaue=form #}
        xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset-urlencoded; charset-UTF-8 ');
        xhr.send("p=456");
    }

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

總結:

Ajax,偷偷向後臺發請求

  -XMLHttpRequest

  -手動使用

  -jQuery

 

「僞」AJAX

  -iframe標籤

  -form表單

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

urls.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'^index.html$', views.index),
    url(r'^ajax1.html$', views.ajax1),

]

views.py

from django.shortcuts import render
from django.shortcuts import HttpResponse
from app01 import models


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


def ajax1(request):
    print(request.GET)
    print(request.POST)
    print(request.body)
    ret = {'status': True, 'message': '...'}
    import json
    return HttpResponse(json.dumps(ret))

index.html

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

    <style>
        .bin {
            display: inline-block;
            padding: 5px 10px;
            background-color: coral;
            color: white;
        }
    </style>

</head>
<body>

<h3>三、莆田</h3>
<div>
    <h6>基於Iframe+Form表單</h6>
    <iframe id="iframe" name="ifra"></iframe>
    <from id="fm" action="/ajax1.html" method="POST" target="ifra">
        <input name="root" value="111111" />
        <input type=submit"  value="提交" />
    </from>

</div>

<script src="/static/js/jquery-3.1.1.js"></script>
<script>

    function Test1() {
        var url = $('#url').val();
        $('#iframe').attr('src',url);
    }

    function AjaxSubmit5() {
        document.getElementById('fm').submit();
    }

    function reloadframe() {
        var content = this.contentWindow.document.body.innerHTML;
        var obj = JSON.parse(content);
        if(obj.status){
            alert(obj.message);
        }
    }

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

jQuery Ajax

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

  • jQuery 不是生產者,而是大天然搬運工。
  • jQuery Ajax本質 XMLHttpRequest 或 ActiveXObject 

注:2.+版本再也不支持IE9如下的瀏覽器

jQuery Ajax 方法列表

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:設置請求超時時間(毫秒)

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

Ajax上傳文件

  - jQuery

  -原生

 以上兩種方式可利用fromData對象,來封裝用戶提交的數據

 - Iframe+Form

 

示例: 文件上傳

 urls.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'^index.html$', views.index),
    url(r'^ajax1.html$', views.ajax1),
]

views.py

from django.shortcuts import render
from django.shortcuts import HttpResponse
from app01 import models


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


def ajax1(request):
    print(request.GET)
    print(request.POST)
    print(request.FILES)   #image/1.jpg
    ret = {'status': True, 'message': '...'}
    import json
    return HttpResponse(json.dumps(ret))

index.html

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

    <style>
        .bin {
            display: inline-block;
            padding: 5px 10px;
            background-color: coral;
            color: white;
        }
    </style>

</head>
<body>

    <h6>基於Iframe+Form表單</h6>
    <div>
        <iframe id="iframe" name="ifra"></iframe>
        <from id="fm" action="/ajax1.html" method="POST" target="ifra">
            <input name="root" value="111111"/>
            <a onclick="AjaxSubmit5()">提交</a>
        </from>
    </div>

    <h3>4.文件上傳</h3>
    <input type="file" id="img"/>
    <a class="bin" onclick="AjaxSubmit6();">上傳</a>
    <a class="bin" onclick="AjaxSubmit7();">上傳</a>

    <iframe style="display: none" id="iframe" name="ifra1"></iframe>
    <from id="fm1" action="/ajax1.html" method="POST" enctype="multipart/form-data" target="ifra1">
        <input type="text" id="k1" />
        <input type="text" id="k2" />
        <input type="file" id="k3" />
        <a onclick="AjaxSubmit8()">提交</a>
    </from>


    <script src="/static/js/jquery-3.1.1.js"></script>
    <script>
        function AjaxSubmit6() {
            var data = new FormData();
            data.append('k1', 'v1');
            data.append('k2', 'v2');
           {# 選擇器,索引0代指上傳的文件對象#}
            data.append('k3',document.getElementById('img').files[0]);

            $.ajax({
                url: '/ajax1.html',
                type: 'POST',
                data: data,
                success: function (arg) {
                    console.log(arg)
                },
                processData: false,
                contentType: false
            })
        }

        function AjaxSubmit7() {
            var data = new FormData();
            data.append('k1', 'v1');
            data.append('k2', 'v2');
            data.append('k3',document.getElementById('img').files[0]);

            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4) {
                    //接收完畢服務器返回的數據
                    console.log(xhr.responseText);
                }
            };
            xhr.open('POST', '/ajax1.html');
            xhr.send(data);
        }

        function AjaxSubmit8() {
            document.getElementById('iframe1').onload = reloadframe1;
            document.getElementById('fm1').submit();
        }

        function reloadframe1() {
            var content = this.contentWindow.document.body.innerHTML;
            var obj = JSON.parse(content);
            console.log(obj);
        }
    </script>
</body>
</html>

示例:實現文件上傳,自動提交

urls.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'^upload.html$', views.upload),
    url(r'^upload_img.html$', views.upload_img),
]

views.py

from django.shortcuts import render
from django.shortcuts import HttpResponse
from app01 import models
import json
import os
import uuid



def upload(request):
    return render(request,'upload.html')

def upload_img(request):
    nid = str(uuid.uuid4())
    ret = {'status':True,'data':None,'message':None}
    obj = request.FILES.get('k3')

    file_path = os.path.join('static', nid+obj.name)
    f = open(obj.name,'wb')
    for line in obj.chunks():
        f.write(line)
    f.close()
    ret['data'] = file_path
    return HttpResponse(json.dumps(ret))

upload.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .btn{
            display: inline-block;
            padding: 5px 10px;
            background-color: coral;
            color: white;
        }
    </style>
</head>
<body>

    <iframe style="display: none" id="iframe1" name="ifra1"></iframe>
    <form id="fm1" action="/upload_img.html" method="POST" enctype="multipart/form-data" target="ifra1">
        <input type="file" name="k3" onchange="uploadFile();" />
    </form>
    <h3>預覽</h3>
    <div id="preview">
    </div>
    <script src="/static/js/jquery-3.1.1.js"></script>
    <script>

        function uploadFile() {
            document.getElementById('iframe1').onload = reloadIframe1;
            document.getElementById('fm1').submit();
        }
        function reloadIframe1() {
            var content = this.contentWindow.document.body.innerHTML;
            var obj = JSON.parse(content);

            var tag = document.createElement('img');
            tag.src = obj.data;
            $('#preview').empty().append(tag);
        }
    </script>
</body>
</html>

跨域AJAX,JSONP

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

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

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

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

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

瀏覽器同源策略:XMLHttpRequest
巧妙的機制JSONP

JSONP:
利用建立script塊,在期中執行src屬性爲:遠程url
函數(返回值)

function 函數(arg){

}

一、JSONP實現跨域請求

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

目錄結構

 

示例:

urls.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.html$', views.jsonp),
    url(r'^ajax3.html$', views.ajax3),
]

views.py

from django.shortcuts import render
from django.shortcuts import HttpResponse
from app01 import models


def jsonp(request):
    return render(request, 'jsonp.html')


def ajax3(request):
    return HttpResponse('本服務器發送的請求')

jsonp.html

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

</head>
<body>

    <div id="content"></div>
    <input type="button" value="發送1" onclick="submitJsonp1();" />
    <input type="button" value="發送2" onclick="submitJsonp2();" />
    <input type="button" value="發送3" onclick="submitJsonp3();" />
    <input type="button" value="發送4" onclick="submitJsonp4();" />
    <script src="/static/js/jquery-3.1.1.js"></script>
    <script>
        function submitJsonp1() {
            $.ajax({
                url: '/ajax3.html',
                type: 'GET',
                data: {nid:2},
                success:function (arg) {
                    $('#content').html(arg);
                }
            })
        }

        function submitJsonp2() {
            var tag = document.createElement('script');
            tag.src = 'http://127.0.0.1:9000/xiaokai.html';
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }

        function fuck(arg) {
            $('#content').html(arg);
        }

        function submitJsonp3() {
            var tag = document.createElement('script');
            tag.src = 'http://www.jxntv.cn/data/jmd-jxtv2.html?callback=list&_=1454376870403';
            document.head.appendChild(tag);
            document.head.removeChild(tag);
        }

       {# function list(arg) {#}
       {# console.log(arg);#}
       {#}#}

        function submitJsonp4() {
            $.ajax({
                url: 'http://127.0.0.1:9000/xiaokai.html',
                type: 'POST',
                dataType: 'jsonp',
                jsonp: 'callback',
                jsonpCallback: 'func'
            })
        }
        function func(arg) {
            console.log(arg);
        }
    </script>
</body>
</html>

另外一個返回數據頁面

urls.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'^xiaokai.html/',views.xiaokai),
]

views.py

from django.shortcuts import render
from django.shortcuts import HttpResponse

# Create your views here.

def xiaokai(request):

    return HttpResponse('fuck("我愛北京天安門");')

 

二、CORS

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

相關文章
相關標籤/搜索