一、引子
我現在開啟了兩個django項目,分別叫Demo1和Demo2,Demo1中有一個路徑‘http://127.0.0.1:8000/index/’,對應的視圖是index視圖返回一個index頁面,頁面中只有一個button按鈕,按鈕綁定了一個單擊事件,點擊之后會發送一個ajax請求,請求的路徑為‘http://127.0.0.1:8001/ajax/’,Demo1的ip和端口號是:‘http://127.0.0.1:8000/’,Demo2的ip和端口號是:‘http://127.0.0.1:8001/’。前面一段描述就是在Demo1項目的一個頁面向Demo2項目發送一個ajax請求,在Demo2有對應的路徑和視圖來處理請求,並返回值。我們運行一下。報錯如下:

這就是一個已攔截的跨域請求的錯誤,錯誤內容是CORS頭少“Access-Control-Allow-Origin”。這就是我們用ajax發送一個跨域請求出現的錯誤,這就是今天我要處理的一個問題。
二、同源策略
同源策略(Same origin policy)是一種約定,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,則瀏覽器的正常功能就會受到影響,可以說web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現。
同源策略,它是由Netscape提出的一個著名的安全策略。現在所有支持JavaScript的瀏覽器都會用這個策略。所謂的同源,即指:域名、端口、協議同時相同。比如說你用ajax發請求時,會檢查你發送的請求是否發送路徑是否ajax所在的JavaScript屬於同源,即是兩者的ip、端口、協議相同。如果不是同源,瀏覽器就會報錯,提示拒絕訪問。
想要實現用ajax發送跨域請求有兩種方式,一是jsonp,而是cors。
三、基於JSONP的ajax跨域請求
1,版本1
我們在用script引入js代碼,有時用的是網上路徑,意思就是在我們的項目去請求其他項目的,如:

這種情況下是可以請求成功的,於是,我們可以運用這一功能,給button按鈕綁定事件,事件的功能是創建一個script標簽,然后添加到頁面上,這樣當我們點擊button按鈕就會發送一個跨域請求,而且還是允許的。
Demo1項目index.html頁面上添加js代碼:
function get_ele_script(url){ var ele_script=$('<script>'); ele_script.attr('src',url); ele_script.attr('id','ele_script'); $('body').append(ele_script); $('#ele_script').remove() } $('.cli').click(function () { get_ele_script('http://127.0.0.1:8001/ajax/') })
這樣就成功用點擊事件發送了一個跨域請求,在Demo2的視圖中,有返回值,但如果我不定義返回的值,HTML文件就會報沒有定義的錯誤,而且視圖返回的值在前端頁面是以變量的形式顯示。
Demo2項目的視圖:
def ajax(request): dic={'name':'zhnag','age':46} dic_json=json.dumps(dic) return HttpResponse('f(%s)'%dic_json)
此時,我們就應該在HTML文件中定義f()
function f(params) {
console.log(params);
console.log(typeof params);
}
這樣,當我們點擊button時,會往Demo2發送一個請求,Demo2會返回帶參數的f(),由於已經定義了f()函數,所以當返回時會執行這個函數,這種方法就實現了發送跨域請求,然后接受返回值,並對返回值進行處理。
2,版本2
其實版本1在Demo2項目中把返回的函數名寫死了,如果照版本1,所有來反問Demo2的瀏覽器都會得到一個叫f()的函數,我們在聲明的時候也只能寫成f()。其實我們可以這樣在請求的時候把我們定義的函數名一起發過去,讓他就給我返回我發送過去的函數,這樣,我們定義函數名就可以隨意了。
Demo1項目的index.html頁面上就應這樣寫:
function f(params) {
console.log(params);
console.log(typeof params);
}
$('.cli').click(function () {
get_ele_script('http://127.0.0.1:8001/ajax/?callbacks=f')
Demo2項目的視圖:
def ajax(request): a=request.GET.get('callbacks') dic={'name':'zhnag','age':46} dic_json=json.dumps(dic) return HttpResponse('%s(%s)'%(a,dic_json))
3,版本3
上面兩個版本就沒有基於ajax請求,這個版本就基於ajax發送跨域請求。
Demo1項目下的index.html頁面上:
function f(params) { console.log(params); console.log(typeof params); } $('.cli').click(function () { $.ajax({ url:'http://127.0.0.1:8001/ajax/callbacks=f', type:'GET', dataType:'jsonp', }) })
Demo2項目的視圖:
def ajax(request): a=request.GET.get('callbacks') dic={'name':'zhnag','age':46} dic_json=json.dumps(dic) print(type(dic_json)) return HttpResponse('%s(%s)'%(a,dic_json))
4,版本4
這也是基於ajax發送的跨域請求,只是比上一版本更簡單。
Demo1項目下的index.html:
function f(params) {
console.log(params);
console.log(typeof params);
}
$('.cli').click(function () {
$.ajax({
url:'http://127.0.0.1:8001/ajax/',
type:'GET',
dataType:'jsonp',
jsonp:'callbacks',
jsonpCallback:'f'
})
})
Demo2項目的視圖:
def ajax(request): a=request.GET.get('callbacks') dic={'name':'zhnag','age':46} dic_json=json.dumps(dic) print(type(dic_json)) return HttpResponse('%s(%s)'%(a,dic_json))
5,版本5(終極版本)
基於ajax的跨域請求,並把返回值給ajax的success。
Demo1項目下的index.html:
$('.cli').click(function () {
$.ajax({
url:'http://127.0.0.1:8001/ajax/',
type:'GET',
dataType:'jsonp',
jsonp:'callbacks',
success:function (data) {
console.log(data)
}
})
})
Demo2項目下的視圖:
def ajax(request): a=request.GET.get('callbacks') dic={'name':'zhnag','age':46} dic_json=json.dumps(dic) return HttpResponse('%s(%s)'%(a,dic_json))
這個版本就比較簡單,書寫方便
四、基於CORS的ajax跨域請求
最開始,我們講的報錯是:CORS頭少:‘Access-Control-Allow-Origin’,既然少一個,我們就加一個,就可以了,其實這種方式才是最常用。
Demo1項目下的index.html:
$('.cli').click(function () {
$.ajax({
url:'http://127.0.0.1:8001/ajax/',
type:'get',
data:{'a':1},
success:function (res) {
console.log(res)
}
})
})
Demo2項目下的視圖:
def ajax(request): dic = {'name': 'zhnag', 'age': 46} http=HttpResponse(json.dumps(dic)) http['Access-Control-Allow-Origin']='http://127.0.0.1:8000' #這相當於加了一個白名單,對於‘http://127.0.01:8000’的跨域請求就允許通行 return http
