Python的Django應(yīng)用程序解決AJAX跨域訪問問題的方法
引子
使用Django在服務(wù)器端寫了一個(gè)API,返回一個(gè)JSON數(shù)據(jù)。使用Ajax調(diào)用該API:
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0"/> <title>test</title> </head> <body> <button onclick="showPersonInfo()">點(diǎn)我獲取數(shù)據(jù)</button> </body> <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script> <script> function showPersonInfo(){ $.getJSON( 'http://xxx/account/getuserinfo/', {username: "abc"}, function(json) { var html='<br>'+'用戶名:'+json.username+'<br>'+'姓:'+json.first_name+'<br>'+'名:'+json.last_name+'<br>'+'郵箱'+json.email; document.write(html); } ) } </script> </html>
但是,Chrome瀏覽器提示錯(cuò)誤:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
經(jīng)過一番Google發(fā)現(xiàn)這個(gè)問題是——CORS導(dǎo)致的。
什么是CORS?
CORS(跨域資源共享,Cross-Origin Resource Sharing)是一種跨域訪問的機(jī)制,可以讓Ajax實(shí)現(xiàn)跨域訪問。
其實(shí),在服務(wù)器的response header中,加入“Access-Control-Allow-Origin: *”即可支持CORS,非常的簡單,apache/nginx等怎么配置,見參考文檔。
舉個(gè)例子:
- API部署在DomainA上;
- Ajax文件部署在DomainB上,Ajax文件會(huì)向API發(fā)送請求,返回?cái)?shù)據(jù);
- 用戶通過DomainC訪問DomainB的Ajax文件,請求數(shù)據(jù)
以上過程就發(fā)生了跨域訪問。如果直接使用Ajax來請求就會(huì)失敗,就像Chrome提示的:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
如何解決Ajax跨域訪問問題?
解決跨域問題,有兩個(gè)方法:1.使用jsonp 2.使CORS生效
使用jsonp方法,需要讓服務(wù)器端放回jsonp格式的response,如Django可以加jsonp相關(guān)的decorator,如:https://coderwall.com/p/k8vb_a/returning-json-jsonp-from-a-django-view-with-a-little-decorator-help由于我不太喜歡這種方式,所以這里略過了,可看后面的參考資料。
使用CORS:這個(gè)用起來比較方便,現(xiàn)在大多數(shù)瀏覽器都支持了,且我web服務(wù)器完全開放給別人調(diào)用,所以比較推薦CORS。
1.使用JSONP
使用Ajax獲取json數(shù)據(jù)時(shí),存在跨域的限制。不過,在Web頁面上調(diào)用js的script腳本文件時(shí)卻不受跨域的影響,JSONP就是利用這個(gè)來實(shí)現(xiàn)跨域的傳輸。因此,我們需要將Ajax調(diào)用中的dataType從JSON改為JSONP(相應(yīng)的API也需要支持JSONP)格式。
JSONP只能用于GET請求。
2.直接修改Django中的views.py文件
修改views.py中對應(yīng)API的實(shí)現(xiàn)函數(shù),允許其他域通過Ajax請求數(shù)據(jù):
def myview(_request): response = HttpResponse(json.dumps({"key": "value", "key2": "value"})) response["Access-Control-Allow-Origin"] = "*" response["Access-Control-Allow-Methods"] = "POST, GET, OPTIONS" response["Access-Control-Max-Age"] = "1000" response["Access-Control-Allow-Headers"] = "*" return response
3.安裝django-cors-headers
這里還有一各發(fā)現(xiàn)!在Django中,有人開發(fā)了CORS-header的middleware,只在settings.py中做一些簡單的配置即可,見:https://github.com/ottoyiu/django-cors-headers/現(xiàn)在用起來服務(wù)器端完全開放,開啟CORS,沒有跨域煩惱,真爽!~
安裝django-cors-headers:
pip install django-cors-headers
在settings.py中增加:
INSTALLED_APPS = ( ... 'corsheaders', ... ) ... MIDDLEWARE_CLASSES = ( ... 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', ... )
可以配置允許跨域訪問的白名單或者直接設(shè)置為允許所有的跨域訪問,具體的配置可以看看他們的github頁說明。
相關(guān)文章
python編程-將Python程序轉(zhuǎn)化為可執(zhí)行程序[整理]
python編程-將Python程序轉(zhuǎn)化為可執(zhí)行程序[整理]...2007-04-04Python實(shí)現(xiàn)一維插值方法的示例代碼
插值主要用于物理學(xué)數(shù)學(xué)中,逼近某一確定值的方法,是通過已知的離散數(shù)據(jù)求未知數(shù)據(jù)的方法。本文將利用Python實(shí)現(xiàn)一維插值方法,需要的可以參考一下2022-04-04python正則表達(dá)式re之compile函數(shù)解析
這篇文章主要介紹了python正則表達(dá)式re之compile函數(shù)解析,介紹了其定義,匹配模式等相關(guān)內(nèi)容,具有一定參考價(jià)值,需要的朋友可以了解下。2017-10-10