Django=フレームワークで作成しているWebアプリケーションにjqueryを統合しようとしています。ただし、単純なajax
呼び出しを実行しようとすると、苦労しています。テンプレートajax呼び出しを処理するためのフォームhtmlおよびjavascriptを含むファイルは次のようになります。
<script type="text/javascript">
$(document).ready(function() {
$( "#target" ).submit(function() {
console.log('Form was submitted');
$.ajax({
type: "POST",
url: "/hello/", // or just url: "/my-url/path/"
data: {
query: $( "#query" ).val()
},
success: function(data) {
console.log(data);
}
});
return false;
});
})
</script>
<form id="target" action="." method="post">{% csrf_token %}
<input id= "query" type="text" value="Hello there">
<input type="submit" value="Search Recent Tweets">
</form>
Ajax呼び出しを処理することになっている私のviews.py
は次のようになります。
from Django.core.context_processors import csrf
from Django.shortcuts import render_to_response
from Django.template.loader import get_template
from Django.template import Context,RequestContext
from Django.views.decorators.csrf import ensure_csrf_cookie
from Django.http import HttpResponse
# access resource
def hello(request):
c = {}
c.update(csrf(request))
if request.is_ajax():
t = get_template('template.html')
#html = t.render(Context({'result': 'hello world'}))
con = RequestContext(request, {'result': 'hello world'})
return render_to_response('template.html', c, con)
else:
return HttpResponse('Not working!')
Cross-Site Request Forgery Protection の公式ドキュメントを追うことを試みましたが、同様の問題に対処するstackoverflowの質問もいくつか見ました。 html
テンプレートファイルに{% csrf_token %}
を含めましたが、まだ機能していないようです。コンソールにajax呼び出しが失敗したことを示すエラーが表示されます。
POST http://127.0.0.1:8000/hello/ 403 (FORBIDDEN)
result
変数をhttp応答とともに渡し、ajax呼び出しをスムーズに動作させるにはどうすればよいですか?どんな助けも大歓迎です。
Edit-1
おそらく、投稿リクエストとともにcsrf
トークンを渡すことはありませんでした。 SOドキュメントに従って、テンプレートjavascriptに次のコードを追加しました。
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;
}
var csrftoken = getCookie('csrftoken');
console.log(csrftoken);
//Ajax call
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
crossDomain: false, // obviates need for sameOrigin test
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type)) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
ブラウザーでテンプレートhtmlページを更新すると、コンソールにnull
が表示され、Cookieが設定されていないか定義されていないことが示唆されます。私は何が欠けていますか?
csrfmiddlewaretokenを投稿しなかったため、Django禁止します。 このドキュメント できます助けます。
怠け者の場合:
最初のCookieのダウンロード: http://plugins.jquery.com/cookie/
HTMLに追加します。
<script src="{% static 'designer/js/jquery.cookie.js' %}"></script>
これで、有効なPOSTリクエストを作成できます:
var csrftoken = $.cookie('csrftoken');
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
$.ajax(save_url, {
type : 'POST',
contentType : 'application/json',
data : JSON.stringify(canvas),
success: function () {
alert("Saved!");
}
})
以前の回答はすべてその場で見つけましたが、状況を把握しましょう。
403の禁止された応答は、CSRFミドルウェアからのものです( Cross Site Request Forgery protection を参照):
デフォルトでは、着信リクエストがCsrfViewMiddlewareによって実行されるチェックに失敗すると、「403 Forbidden」応答がユーザーに送信されます。
多くのオプションが利用可能です。 jQueryにX-CSRFToken
を伴うすべてのAJAX=リクエストの前に$.ajaxSetup
ヘッダーを追加させるには、 @ fivefの答え に従うことをお勧めします。
この回答には、cookie jQueryプラグインが必要です。これが望ましくない場合、別の可能性は追加することです:
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;
}
var csrftoken = getCookie('csrftoken');
しかし: CSRF_COOKIE_HTTPONLY
設定がTrueに設定されている場合、 セキュリティミドルウェア が推奨するように頻繁に発生するため、@ensure_csrf_cookie()
が使用されます。この場合、{% csrf_token %}
をすべてのフォームで提供する必要があり、<input name="csrfmiddlewaretoken" value="cr6O9...FUXf6" type="hidden">
などの出力が生成されます。そのため、csrfToken
変数は次のようにして簡単に取得できます。
var csrftoken = $('input[name="csrfmiddlewaretoken"]').val();
もちろん、$.ajaxSetup
はもちろん必要です。
利用可能な他のオプションは推奨されませんは、@csrf_exempt()
で特定のフォームのミドルウェアまたはcsrf保護を無効にすることです。
テンプレートにjsを埋め込まない場合の最速のソリューションは次のとおりです。
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
テンプレート内のscript.jsファイルへの参照の前に、csrfmiddlewaretoken
をdata
辞書に追加します。
$.ajax({
type: 'POST',
url: somepathname + "do_it/",
data: {csrfmiddlewaretoken: window.CSRF_TOKEN},
success: function() {
console.log("Success!");
}
})
Jsをテンプレートに埋め込む場合、次のように簡単です:data: {csrfmiddlewaretoken: '{{ csrf_token }}'}
Cookieを設定するには、 ensure_csrf_cookie
ビューのデコレータ:
from Django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def hello(request):
code_here()
フォームが表示されているページ/ビューをキャッシュしていないことを確認してください。 CSRF_TOKENをキャッシュしている可能性があります。私に起こりました!
data: {"csrfmiddlewaretoken" : "{{csrf_token}}"}
「csrfmiddlewaretoken」パラメーターを送信しないため、「403(FORBIDDEN)」が表示されます。テンプレートでは、各フォームに{%csrf_token%}があります。 「csrfmiddlewaretoken」をajaxデータ辞書に追加する必要があります。私の例では、「product_code」と「csrfmiddlewaretoken」をアプリ「basket」ビュー「remove」に送信しています。
$(function(){
$('.card-body').on('click',function(){
$.ajax({
type: "post",
url: "{% url 'basket:remove'%}",
data: {"product_code": "07316", "csrfmiddlewaretoken" : "{{csrf_token}}" }
});
})
});
このデコレータをディスパッチコードに含めてみてください
from Django.utils.decorators import method_decorator
from Django.views.decorators.csrf import csrf_exempt
@method_decorator(csrf_exempt, name='dispatch')
def dispatch(self, request, *args, **kwargs):
return super(LessonUploadWorkView,self).dispatch(request,*args,**kwargs)
SSL/httpsおよびCSRF_COOKIE_HTTPONLY = Falseの場合、 Django Doc で提案されているgetCookie(name)関数を使用するか、またはjquery.cookie.jsfivef によって提案されました。
Wtower summaryは完璧で、settings.pyからCSRF_COOKIE_HTTPONLYを削除した後でも機能すると思いましたが、httpsでは機能しません!
csrftokenがdocument.cookieに表示されない理由???
取得する代わりに
「Django_language = fr; csrftoken = rDrGI5cp98MnooPIsygWIF76vuYTkDIt」
しか得られない
「Django_language = fr」
どうして? SSL/httpsのようにheaders からX-CSRFTokenを削除します。これはNginxのプロキシヘッダーパラメーターによるものと思われますが、明らかにそうではありません。
Django doc Notes とは異なり、httpsでcookie内のcsrf_tokenを操作することは不可能のようです。 csrftokenを渡す唯一の方法は、HTMLで{%csrf_token%}を使用してDOMを介し、jQueryで取得することです。
var csrftoken = $('input[name="csrfmiddlewaretoken"]').val();
その後、ヘッダー( xhr.setRequestHeader )または params によってajaxに渡すことができます。