Django POST请求失败

0 投票
2 回答
2939 浏览
提问于 2025-04-17 16:50

我在用表单发送POST请求时遇到了一个错误,虽然我已经在表单中添加了csrf_token。

错误信息

禁止访问 (403)

CSRF验证失败。请求被中止。

求助

失败的原因: CSRF cookie没有设置。

一般来说,这种情况可能是因为发生了真正的跨站请求伪造(Cross Site Request Forgery),或者是Django的CSRF机制没有正确使用。对于POST表单,你需要确保以下几点: • 你的浏览器可以接受cookies。 • 视图函数使用的是RequestContext来渲染模板,而不是Context。 • 在模板中,每个指向内部网址的POST表单里都要有一个{% csrf_token %}标签。 • 如果你没有使用CsrfViewMiddleware,那么在任何使用csrf_token标签的视图,以及那些接受POST数据的视图上,必须使用csrf_protect。

你看到这个帮助部分是因为你的Django设置文件中DEBUG = True。把它改成False后,只会显示最初的错误信息。

你可以通过CSRF_FAILURE_VIEW设置来自定义这个页面。

views.py

def search_form(request):
    return render_to_response('search_form.html')
def search(request):
    print 'request.post=', request.POST
    print 'request.get=', request.GET
    print 'request.method=', request.META.get('REQUEST_METHOD')
    if 'q' in request.GET:
        message = 'You searched for :%r' % request.GET['q']
    else:
        message = 'You submitted an empty form'

    return HttpResponse(message)



search-form.html

<html>
<head>
    <title>Search</title>
</head>
<body>
    <form action="/polls/search/" method="post">{% csrf_token %}
        <input type="text" name="q">
        <input type="submit" value="Search">
    </form>
</body>
</html>

urls.py
urlpatterns = patterns('',url(r'^$',views.index,name='index'),
        url(r'^meta/',views.display_meta,name='meta'),
        url(r'^search-form/$',views.search_form),
        url(r'^search/',views.search),

2 个回答

2

你可以在这里查看第3点。你现在返回的是一个普通的HttpResponse,所以我觉得csrf上下文处理器可能被跳过了。你可以考虑使用django.shortcuts.render来代替。另外,在你的模板中,表单的方法是“post”,但在你的视图中,你却在检查request.GET。这和你遇到的CSRF问题没有直接关系,但这可能是你需要修正的地方。

0

你还没有把令牌加到你的表单里。

你虽然加了代码 {% csrf_token %},但是 django.core.context_processors.csrf 并没有被使用,所以这个模板标签实际上没有输出任何东西(模板标签不会报错,只是默默失败)。

你需要用 render_to_response()(配合 RequestContext)来替代 HttpResponse,或者直接用 render()(这个方法会自动处理 RequestContext)。

另外,你其实不需要两个视图来处理这个。search 应该同时负责渲染表单和处理表单。

从 django.shortcuts 导入 render

def search(request):
    if request.method == POST:
        print 'request.post=', request.POST
        print 'request.get=', request.GET
        print 'request.method=', request.META.get('REQUEST_METHOD')
        if 'q' in request.GET:
            message = 'You searched for :%r' % request.POST['q']
        else:
            message = 'You submitted an empty form'
        return render(request, 'search_form.html', {'message': message})
    return render(request, 'search_form.html')

然后把 {{ message }} 变量加到你的 search_form.html 模板里 - 可能需要用某种 if 语句来实现你现在正在做的事情 -

<body>
    {% if message %}
        <div> {{ message }} </div>
    {% else %}
        <form action="/polls/search/" method="post">{% csrf_token %}
            <input type="text" name="q">
            <input type="submit" value="Search">
        </form>
    {% endif %}
</body>

撰写回答