我正在尝试将jquery集成到我正在使用Django框架创建的Web应用程序中。然而,我正在努力做一个简单的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问题。我已将{% csrf_token %}
添加到我的html
模板文件中,但它似乎仍无效。我在控制台中收到错误,提示ajax调用失败:
POST http://127.0.0.1:8000/hello/ 403 (FORBIDDEN)
如何将result
变量与我的http响应一起传递并让ajax调用顺利运行?非常感谢任何帮助。
修改-1
我不应该将csrf
令牌与我的帖子请求一起传递。因此,根据文档,我将以下代码添加到我的模板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未设置或未定义。我错过了什么?
答案 0 :(得分:42)
因为你没有发布 csrfmiddlewaretoken ,所以Django禁止你。 this document可以帮助您。
答案 1 :(得分:21)
对于懒惰的人:
首先下载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!");
}
})
答案 2 :(得分:5)
我现场找到所有以前的答案,但让我们把事情放在上下文中。
403禁止响应来自CSRF中间件(参见Cross Site Request Forgery protection):
默认情况下,如果传入请求未通过CsrfViewMiddleware执行的检查,则会向用户发送“403 Forbidden”响应。
有很多选择。我建议遵循answer of @fivef,以便jQuery在X-CSRFToken
的每个AJAX请求之前添加$.ajaxSetup
标头。
这个答案需要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,这通常是Security middleware建议的那样,那么即使使用@ensure_csrf_cookie()
,Cookie也不存在。在这种情况下,必须在每种形式中提供{% csrf_token %}
,这会产生<input name="csrfmiddlewaretoken" value="cr6O9...FUXf6" type="hidden">
等输出。因此csrfToken
变量只需通过以下方式获得:
var csrftoken = $('input[name="csrfmiddlewaretoken"]').val();
当然需要$.ajaxSetup
。
其他可用但不推荐的选项是使用@csrf_exempt()
禁用特定表单的中间件或csrf保护。
答案 3 :(得分:3)
如果不将js嵌入模板,最快的解决方案是:
在模板中对script.js文件的引用之前放入<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
,然后将csrfmiddlewaretoken
添加到data
字典中:
$.ajax({
type: 'POST',
url: somepathname + "do_it/",
data: {csrfmiddlewaretoken: window.CSRF_TOKEN},
success: function() {
console.log("Success!");
}
})
如果您确实将js嵌入到模板中,则非常简单:data: {csrfmiddlewaretoken: '{{ csrf_token }}'}
答案 4 :(得分:2)
要设置Cookie,请在视图中使用ensure_csrf_cookie
装饰器:
from django.views.decorators.csrf import ensure_csrf_cookie
@ensure_csrf_cookie
def hello(request):
code_here()
答案 5 :(得分:1)
确保您没有缓存表单所显示的页面/视图。它可以缓存您的CSRF_TOKEN。发生在我身上!
答案 6 :(得分:1)
尝试在您的调度代码中包含此装饰器
dumpcap -d ${filter1}
答案 7 :(得分:1)
另一种方法是将X-CSRFTOKEN标头添加为“ {{csrf_token}}”值,如以下示例所示:
$.ajax({
url: "{% url 'register_lowresistancetyres' %}",
type: "POST",
headers: {//<==
"X-CSRFTOKEN": "{{ csrf_token }}"//<==
},
data: $(example_form).serialize(),
success: function(data) {
//Success code
},
error: function () {
//Error code
}
});
答案 8 :(得分:0)
使用SSL / https且CSRF_COOKIE_HTTPONLY = False,我仍然没有在cookie中使用csrftoken,使用django Doc或 getCookie(name)函数> {jquery.cookie.js 由fivef提出。
Wtower摘要非常完美,我认为从settings.py中删除CSRF_COOKIE_HTTPONLY后它会起作用,但它在https中没有!
为什么在document.cookie中看不到csrftoken ???
而不是
“django_language = fr; csrftoken = rDrGI5cp98MnooPIsygWIF76vuYTkDIt”
我只得到
“django_language = FR”
为什么?就像SSL/https removes X-CSRFToken from headers我认为这是由于Nginx的代理标题参数,但显然不是......任何想法?
与django doc Notes不同,似乎无法在使用https的cookie中使用csrf_token。传递csrftoken的唯一方法是通过在html中使用{%csrf_token%}来通过DOM,并使用
在jQuery中获取它var csrftoken = $('input[name="csrfmiddlewaretoken"]').val();
然后可以通过标题(xhr.setRequestHeader)将其传递给ajax,或者params。
答案 9 :(得分:0)
data: {"csrfmiddlewaretoken" : "{{csrf_token}}"}
您看到“ 403(FORBIDDEN)”,因为您没有发送“ csrfmiddlewaretoken”参数。 在模板中,每种形式都具有以下内容:{%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}}" }
});
})
});
答案 10 :(得分:0)
这对我有用
模板.html
$.ajax({
url: "{% url 'XXXXXX' %}",
type: 'POST',
data: {modifica: jsonText, "csrfmiddlewaretoken" : "{{csrf_token}}"},
traditional: true,
dataType: 'html',
success: function(result){
window.location.href = "{% url 'XXX' %}";
}
});
view.py
def aggiornaAttivitaAssegnate(request):
if request.is_ajax():
richiesta = json.loads(request.POST.get('modifica'))
答案 11 :(得分:-3)
您必须更改文件夹chmod 755和文件(.php,.html)chmod 644。