Django
で、form
を使わないでpost
する。(jQuery使用)
- 2019/04/27: getCookieとcsrf_tokenの誤字を修正
- 2020/03/15:
$.ajax
パラメータの誤字を修正
Django
でのpost
の解説は、form
を使ったものが多い。
<form method="post">
{% csrf_token %}
<input id="some_value" type="text" name="some_name">
<input id="submit_id" type="submit">
</form>
このような方法ばかり。
button
を押して、ダイアログで確認後にpost
する。という流れを行いたいので、
この方法では実現できないと思う。jQuery
でやると、
Forbidden (CSRF token missing or incorrect.):
が表示され、view
まで行かない。
jQuery
でのリクエスト時に、csrf_token
を埋め込む必要がある。
クロスサイトリクエストフォージェリ (CSRF) 対策 | Django documentation | Django に対応が書かれていた。
html
はこうする。(抜粋)
<!-- formがいらなくなる -->
<button id="button_id">Submit</button>
form
はなく、button
を直接配置する。
次に、Javascript
をこのようにする。(抜粋)
// csrf_tokenの取得に使う
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 csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$(document).on("click", "#button_id", function() {
var button = $(this);
var csrf_token = getCookie("csrftoken");
var rslt = window.confirm("Do you really want to do?");
if (rslt) {
$.ajax({
type: "POST",
url: "SomeUrl",
data: {
"key1": "value1",
"k2": "v2",
},
contentType: "application/json",
// 送信前にヘッダにcsrf_tokenを付与。
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrf_token);
}
},
success: function(data) {
alert(data);
},
error: function(xhr, status, error) {
alert(status + "\n" +
"Status: " + xhr.status + "\n" + error);
}
});
}
});
あとはpython
コードのview
でPOST
を判別して行いたい処理をすればいい。
def some_view(request):
if request.method == 'POST':
from django.http import QueryDict
# request.bodyに入っている。
dic = QueryDict(request.body, encoding='utf-8')
v1 = dic.get('key1')
v2 = dic.get('k2')
r1, r2 = do_something(v1, v2)
from json import dumps
ret = dumps({'k1': r1, 'k2': r2})
return HttpResponse(ret, content_type='application/json')
else:
return do_something_else()
request.POST.get('key')
はパラメータとしては渡されていないので、使えないのだと思う。
(request.POST
は空になる)。
一手間かかるが、QueryDictを自前で作ればほぼ同じようにできる。
微妙に公式docsは読みづらいのが悩み。下のような書籍の方がいいかも。情報は更新されないが……
Python3 + Django2.0入門 - Pythonで作るWebアプリケーション開発入門 - その1
posted with amazlet at 18.11.26
(2018-08-19)
売り上げランキング: 2,178
売り上げランキング: 2,178
コメント