JQuery & Django Ajax 踩過的坑
JQuery & Django Ajax 踩過的坑
現在做一個數據視覺化的專案,由於核心的機器學習程式碼使用python寫的,資料視覺化用的是D3.js 現在要給老大們展示這個結果,於是簡單搭建了一個web application. 個人比較偏向於用Node.js 去完成但是出於程式設計師對技術的摯愛以及之前一直沒有用過python搭建web application. 於是嘗試了一下,但是沒想到其中有這麼多的坑,於是總結了一下自己在開發過程中遇到的一些坑以及解決方法,希望能夠幫助後續的讀者能夠及時解決這些問題,減少在這些問題上的時間損耗
403 forbidden
遇到這種情況從服務端可以看到提示 CSRF cookie not set
的提示。 針對這種情況主流的是兩種解決方式:1.直接disable csrf 驗證的功能,因為本身CSRF為了避免跨站點的指令碼攻擊而引入的機制,但是如果是非生產環境,只是自己試驗的話完全可以考慮disable這個功能;2. 正常使用這個功能,在CSRF work的情況下保證Ajax 成功。個人是比較推薦第二種方法。
Disable CSRF
首先需要在在settings.py裡面的MIDDLEWARE_CLASSES 中加入
django.middleware.csrf.CsrfResponseMiddleware
對於低版本的Django(1.2左右沒有考證過) 新增這一段之後就可以解決問題,但是對於高版本的Django 這一步還沒有完全解決問題,還需要在處理http請求的python程式碼裡面如下的程式碼:
from django.views.decorators.csrf import csrf_exempt
...
@csrf_exempt
def my_post(request):
return HttpResponse('test')
如此才能夠通過disable CSRF 的方式讓程式正常執行起來。
Enable CSRF
在實現正常的enable CSRF 的情況下完成ajax處理之前,第一步需要了解Django中的引入的CSRF到底是什麼,它的執行機制又是什麼。關於CSRF參考我的另外一篇blog. CSRF(cross-site request forgery) 跨站點請求偽造。如果要保證CSRF機制正常運轉的,實現Ajax功能需要完成如下的幾點:第一,請求中攜帶csrf_token
{% csrf_token %}
即可例子如下:
<form method="POST" action="/postinf">
{% csrf_token %}
<input type="text" name="t_csrf"/>
<input type="submit" value="Submit"/>
</form>
如果沒有新增token 一般出現錯誤是CSRF cookie not set
然後是ajax 請求下的token 問題,最簡單一個方案,在執行Ajax call 之前新增如下程式碼:
$.ajaxSetup({
data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});
例子如下:
$(document).ready(function(){
$.ajaxSetup({
data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});
function ajaxhandler(data,status){
alert(data);
}
$("#bu").click(function(){
$.post("/ajax_post",{"id":1},ajaxhandler);
});
});
最終能夠正常實現ajax獲取服務端資料.
JQuery Ajax請求URL以及Django中路由配置問題
Django中路由配置依然依賴於字元模式匹配,一個最簡單的例子,配置Django主頁一般在urls.py
中新增如下的配置:
urlpatterns = [
url(r'^$',views.main_page),
]
如果使用JQuery的ajax 功能獲取服務端內容那麼在JavaScript指令碼以及Django的urls.py
中需要特別注意url匹配問題。如下例子,假設指令碼傳送一個POST 請求到服務端獲取資料,傳送請求URL為http://127.0.0.1:8000/postinf
指令碼中寫法如下:
$.post('/postinf',{"id":1},postHandler);
而在於Django的服務端程式urls.py 中應該是如下的配置:
urlpatterns = [
url(r'^$',views.main_page),
url(r'^postinf',views.do_post),
]
比較坑的就是url中的斜線。指令碼中需要新增而服務端配置路由的地方卻不需要新增,不然出現404.
總結
目前專案中使用到Django的功能還比較簡單,後面遇到問題我會及時更新文章。