1. 程式人生 > >JQuery & Django Ajax 踩過的坑

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

. 在get 請求中不需要攜帶token 就能夠正常訪問,而在post 請求中必須攜帶token 不然會報錯。如果是表格的提交(雖然不在Ajax請求的範圍內,但是一般為POST請求,所以需要攜帶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的功能還比較簡單,後面遇到問題我會及時更新文章。