1、引子
我如今開啓了兩個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有對應的路徑和視圖來處理請求,並返回值。咱們運行一下。報錯以下:html
這就是一個已攔截的跨域請求的錯誤,錯誤內容是CORS頭少「Access-Control-Allow-Origin」。這就是咱們用ajax發送一個跨域請求出現的錯誤,這就是今天我要處理的一個問題。前端
2、同源策略
同源策略(Same origin policy)是一種約定,它是瀏覽器最核心也最基本的安全功能,若是缺乏了同源策略,則瀏覽器的正常功能就會受到影響,能夠說web是構建在同源策略基礎之上的,瀏覽器只是針對同源策略的一種實現。web
同源策略,它是由Netscape提出的一個著名的安全策略。如今全部支持JavaScript的瀏覽器都會用這個策略。所謂的同源,即指:域名、端口、協議同時相同。好比說你用ajax發請求時,會檢查你發送的請求是否發送路徑是否ajax所在的JavaScript屬於同源,便是二者的ip、端口、協議相同。若是不是同源,瀏覽器就會報錯,提示拒絕訪問。ajax
想要實現用ajax發送跨域請求有兩種方式,一是jsonp,而是cors。django
3、基於JSONP的ajax跨域請求
1,版本1
咱們在用script引入js代碼,有時用的是網上路徑,意思就是在咱們的項目去請求其餘項目的,如:json
這種狀況下是能夠請求成功的,因而,咱們能夠運用這一功能,給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項目的視圖:app
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))
這個版本就比較簡單,書寫方便
4、基於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