Django POST 请求失败

Posted

技术标签:

【中文标题】Django POST 请求失败【英文标题】:Django POST request failing 【发布时间】:2013-02-08 18:06:29 【问题描述】:

在我的表单中使用 POST 时出现错误,即使我在表单中添加了 csrf_token....

错误

禁止 (403)

CSRF 验证失败。请求中止。

帮助

失败的原因: CSRF cookie 未设置。

一般来说,当有真正的跨站请求伪造时,或者没有正确使用 Django 的 CSRF 机制时,就会发生这种情况。对于 POST 表单,您需要确保: •您的浏览器正在接受cookies。 • 视图函数使用RequestContext 作为模板,而不是Context。 • 在模板中,每个 POST 表单内都有一个 % csrf_token % 模板标签,以内部 URL 为目标。 • 如果您没有使用 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),

【问题讨论】:

【参考方案1】:

您想查看第 3 点 here。您正在返回一个普通的 HttpResponse,所以我认为 csrf 上下文处理器正在被跳过。您可能要考虑改用django.shortcuts.render。此外,在您的模板中,您的表单方法是“发布”,但在您看来,您正在检查 request.GET。这与您遇到的 CSRF 问题无关,但可能是您想要解决的问题。

【讨论】:

【参考方案2】:

您尚未将令牌添加到表单中。

您已添加代码 % csrf_token %,但 django.core.context_processors.csrf 并未被使用,因此模板标签实际上并未输出任何内容(模板标签静默失败)。

您需要render_to_response()(带有RequestContext)或只使用render()(为您处理RequestContext),而不是使用HttpResponse

另一方面,您不需要两个视图。 search 应该同时处理表单的渲染和处理 -

从 django.shortcuts 导入渲染

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>

【讨论】:

以上是关于Django POST 请求失败的主要内容,如果未能解决你的问题,请参考以下文章

django CSRF 验证失败。请求中止

TypeError:网络请求失败(使用 ReactNative 和 Django)

Django的POST请求时因为开启防止csrf,报403错误,及四种解决方法

错误:“CSRF 验证失败。请求中止。”在 Django 中使用 jquery ajax 时

iPhone POST 到 Django 并获得 CSRF 验证失败

我用django接收post请求结果为空