#12 djangoにて、AjaxでPOSTをする
皆さんあけましておめでとうございます。 2013年もどうぞよろしくお願いします、れいです。
さて、へび年です。 へびと言えば?
…そう。Pythonですよね。
今日はdjangoのちょっとしたメモを残します。ただの備忘録になってますが。
PythonのWebフレームワークと言えばお馴染みDjango Pyramidもありますが、今日はdjangoの話です。
さて、djangoは1.2系からCSRFを防ぐために、csrf_tokenを導入しています。
HTMLのformでPOSTをする際には、テンプレートに以下のように書かなければなりません。
<form action="#" method="POST">{\% csrf_token \%}
<input type= ...
こんな風に書くと、実際のhtmlは以下のように出力されます。
<form action="#" method="POST">
<div style='display:none'>
<input type='hidden' name='csrfmiddlewaretoken' value='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' />
</div>
ところで、時代はAjaxです。 非同期で、対話的で、ダイナミックで、リアルタイムなウェブサイトを作るためには、 Ajaxの力を借りるのが一般的でしょう。
こんな風にしましょう
<input type="text" id="test" \>
<input type="data" id="data" \>
これを別のページにPOSTして、 その結果をresultというIDに入れたい!
おそらく、こう書くでしょう。
$("#result").load("/other/page",
{ 'test' : $('#test').val() ,
'data' : $('#data').val() });
ところが、これではdjangoに怒られて、403が帰ってきてしまいます。 それもそのはず、csrf_tokenが無いからです。
対策はいくつかありそうですが、こんなのが推奨されていました。 jQueryのAjaxSend関数を以下のようにする方法です。
jQuery(document).ajaxSend(function(event, xhr, settings) {
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
function sameOrigin(url) {
// url could be relative or scheme relative or absolute
var host = document.location.host; // host + port
var protocol = document.location.protocol;
var sr_origin = '//' + host;
var origin = protocol + sr_origin;
// Allow absolute or scheme relative URLs to same origin
return (url == origin || url.slice(0, origin.length + 1) == origin + '/') ||
(url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin + '/') ||
// or any other URL that isn't scheme relative or absolute i.e relative.
!(/^(\/\/|http:|https:).*/.test(url));
}
function safeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
if (!safeMethod(settings.type) && sameOrigin(settings.url)) {
xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
}
});
何をしているのかというと、XMLHttpRequestに対し、 X-CSRFTokenヘッダの値にcsrftokenの値を付加しています。 (※jQuery1.5以上でしか動作しない模様です)
上記のスクリプトを、ajaxを利用するスクリプトファイルの上部に記述しましょう。 そうすると、特に何も考えずにdjangoのページにAjaxでPOSTすることが出来るようになります。
これで皆さんはdjangoを使って簡単に、 そしてAjaxを使って対話的に、ダイナミックに、インタラクティブに、 Webサイトを作ることが出来るでしょう:-) (※個人の能力によります)
さて、今日書いた事は実はここに書いてあります。 こちらを読むほうが正確でしょう。
へび年なので、新年の挨拶がてらpythonネタを書いてみたかっただけです。 しかしdjangoは本当に簡単でいいですね。 あとjQueryも最近覚え始めましたが、javascriptをベタ書きするより遥かに楽ですごくいいですね。
それでは。