More than 1 year has passed since last update.

JavascriptでPOSTしようとするとDjangoのCSRF対策に引っかかり失敗してしまうことがあるのだが、公式ドキュメントにちゃんと対策が書かれている。
http://docs.djangoproject.jp/en/latest/ref/contrib/csrf.html?highlight=csrf#ajax

なお、使い回せるようにコピペしたものをGithubに上げたので使いたい方はどうぞ。
https://github.com/juniskw/django_tools/blob/master/csrf_token_ajax.js

例:POSTした文字に「!!!」を付けてアラートするアプリ。

surprise.html
<head>
    <script type="text/javascript" src="{{STATIC_URL}}js/jquery-1.11.0.min.js"></script>
    <script type="text/javascript" src="https://raw.githubusercontent.com/juniskw/django_tools/master/csrf_token_ajax.js"></script>
</head>
<body>
    <h1>Let's Surprise!</h1>
    <form id="surprise_fm" action="surprise/" method="post">
        <input id="your_txt" type="text" name="your_txt">
        <input id="surprise_btn" type="submit">
    </form>
</body>
<script>
$(document).ready(function() {
    $('#surprise_fm').submit(function() {  // ボタンクリックでAJAX
        $.ajax({
            'url':$('form#surprise_fm').attr('action'),
            'type':'POST',
            'data':{
                'your_txt':$('#your_txt').val(),
            },
            'dataType':'json',
            'success':function(response){  // 通信が成功したら動く処理で、引数には返ってきたレスポンスが入る
                alert(response.your_surprise_txt);  // レスポンスからデータを取り出してアラート
            },
        });
        return false;
    });
});
</script>
urls.py
#...
url(r'^surprise/', 'views.for_ajax'),
#...
views.py
def for_view(req):    # ビューを表示する関数
    return render(req,'surprise.html')

def for_ajax(req):    # AJAXに答える関数
    import json
    from django.http import HttpResponse,Http404

    if req.method == 'POST':
        txt = req.POST['your_txt']  # POSTデータを取得して
        surprise_txt = txt + "!!!"  # 加工

        response = json.dumps({'your_surprise_txt':surprise_txt,})  # JSON形式に直して・・

        return HttpResponse(response,mimetype="text/javascript")  # 返す。JSONはjavascript扱いなのか・・

    else:
        raise Http404  # GETリクエストを404扱いにしているが、実際は別にしなくてもいいかも

なお、jsを以下のように一部書き変えれば普通に csrf_token をフォームに入れるだけでも問題ない。

$.ajax({
    // ...
    'data':$('form#surprise_fm').serialize(),
    // ...
});

serialize はおそらくform内のinput要素を全て {name:value,...} の形にまとめてくれるメソッドだと思われる。Djangoの csrf_token はタネを明かせば hiddenタイプのinput要素 みたいなので、この方法なら通常のフォーム処理と同様に機能することができるのだろう。

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.