我已阅读Django的- CSRF验证失败和几个到Django和POST方法相关的问题(和答案)。 其中最好的,但并非工作换我的回答是https://stackoverflow.com/a/4707639/755319
所有经批准的答案建议至少三件事情:
- 使用的RequestContext作为render_to_response_call的第三个参数
- 添加{%csrf_token%}与POST方法各种形式
- 检查settings.py中的MIDDLEWARE_CLASSES
我究竟做的建议,但错误还是出现了。 我使用Django 1.3.1(Ubuntu的,从12.04库)和Python 2.7(默认从Ubuntu的)
这是我的看法:
# Create your views here.
from django.template import RequestContext
from django.http import HttpResponse
from django.shortcuts import render_to_response
from models import BookModel
def index(request):
return HttpResponse('Welcome to the library')
def search_form(request):
return render_to_response('library/search_form.html')
def search(request):
if request.method=='POST':
if 'q' in request.POST:
q=request.POST['q']
bookModel = BookModel.objects.filter(title__icontains=q)
result = {'books' : bookModel,}
return render_to_response('library/search.html', result, context_instance=RequestContext(request))
else:
return search_form(request)
else:
return search_form(request)
这是我的模板(search_form.html):
{% extends "base.html" %}
{% block content %}
<form action="/library/search/" method="post">
{% csrf_token %}
<input type="text" name="q">
<input type="submit" value="Search">
</form>
{% endblock %}
我已经重新启动服务器,但禁止403错误仍然存在,告诉CSRF验证失败。
我有2个问题:
- 如何解决这个问题?
- 为什么这么难使Django的一个“POST”,我的意思是有什么特别的原因使它如此冗长(我来自PHP,而且从来没有发现这样的问题)?
尝试把RequestContext的在search_form视图的选择render_to_response:
context_instance=RequestContext(request)
我也许错了,但是我发现相当复杂的上述解决方案。
什么工作对我来说是简单的,包括我的CSRF令牌到我的职务的请求。
$.ajax({
type: "POST",
url: "/reports/",
data: { csrfmiddlewaretoken: "{{ csrf_token }}", // < here
state:"inactive"
},
success: function() {
alert("pocohuntus")
console.log("prototype")
}
})
为了避免此类问题的最简单方法是使用render
快捷。
from django.shortcuts import render
# .. your other imports
def search_form(request):
return render(request, 'library/search_form.html')
def search(request):
q = request.GET.get('q')
results = BookModel.objects.all()
if q:
results = results.filter(title__icontains=q)
return render(request, 'library/search.html', {'result': results})
这个答案是,可能在未来会遇到同样的问题的人。
该CSRF {{csrf_token}}
防止针对跨站点请求伪造模板所需的形式Django的标签。 CSRF它使已经访问过客户端的浏览器发出请求到自己的服务器恶意网站。 因此Django提供的csrf_token变得非常简单了你的Django服务器和站点打击这种类型的恶意攻击的保护。 如果您的形式不受csrf_token保护,Django的返回一个403页禁止。 这是为您的网站的一种保护,特别是当令牌不是故意冷落。
但是,在某些场景下一个Django网站不希望使用csrf_token来保护它的形式。 例如,我公司开发的USSD应用并且需要视图功能以接收来自所述USSD API POST请求。 我们应该注意到,POST请求不是从客户端,因此CSRF不可能的风险上的形式,因为一个恶意网站无法提交请求。 当用户当表单提交拨一个USSD代码,而不是在接收到POST请求。
换句话说,存在其中的功能将需要得到一个POST请求,但不会有必要的情况下{{csrf_token}}。
Django的为我们提供了一个装饰@csrf_exempt
。 这个装饰标志着一个视图是由通过中间件保证了保护豁免。
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
@csrf_exempt
def my_view(request):
return HttpResponse('Hello world')
Django的还提供了执行具有相同功能的另一装饰{{csrf_token}}
但它不拒绝传入请求。 这个装饰是@requires_csrf_token
。 例如:
@requires_csrf_token
def my_view(request):
c = {}
# ...
return render(request, "a_template.html", c)
将在这篇文章提到的最后装饰不正是同样的事情{{csrf_token}},它被称为@csrf_protect
。 然而,若单独使用这种装饰是不是最好的做法,因为你可能会忘记将它添加到你的观点。 例如:
@csrf_protect
def my_view(request):
c = {}
# ...
return render(request, "a_template.html", c)
下面是一些链接,将引导和更好的解释。
https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/#module-django.views.decorators.csrf
https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/
http://www.squarefree.com/securitytips/web-developers.html#CSRF
响应是403个bcoz,Django的要求在每一个岗位一个CSRF令牌(包括在后数据)要求你做。
有多种方法来做到这一点,例如:
从饼干获取单词和方法在文章中说明在此处输入链接的描述
要么
您可以从DOM使用{{csrf_token}}访问它,可在模板中
所以,现在使用第二种方法:
var post_data = {
...
'csrfmiddlewaretoken':"{{ csrf_token }}"
...
}
$.ajax({
url:'url',
type:'POST'
data:post_data,
success:function(data){
console.log(data);
},
error:function(error){
console.log(error);
}
});
您还可以使用
direct_to_template(request, 'library/search.html', result)
代替
render_to_response('library/search.html', result, context_instance=RequestContext(request))
因为direct_to_template
增加RequestContext
自动。 但是请注意, direct_to_template
将被弃用,Django还提供了使用CBV TemplateView
代替。
RequestContext
允许您使用的上下文处理器。 这是你的错误: {% csrf_token %}
outputed空字符串和你有403。
您需要使用RequestContext
根据您的回复
例如在view.py
文件
from django.template import RequestContext
def home(request):
return render_to_response('home.html',RequestContext(request, {}))