Django:添加{% csrf_token %}后仍然出现CSRF验证失败

3 投票
7 回答
8997 浏览
提问于 2025-04-17 07:51

views.py:

def index(request):
    return render_to_response('index.html', {})

def photos(request, artist):
    if not artist:
        return render_to_response('photos.html', {'error' : 'no artist supplied'})
    photos = get_photos_for_artist(artist)
    if not photos:
        logging.error('Issue while getting photos for artist')
        return render_to_response('photos.html', {'error': 'no matching artist found'})
    return render_to_response('photos.html', {'photos': photos})  

Index.html:

<html>
    <head>
        <title>find artist photos </title>
    </head>
    <body>
        {% block error %} {% endblock %}
        <form action="/photos" method="POST">
            {% csrf_token %}
            <label for="artist">Artist : </label>
            <input type="text" name="artist">
            <input type="submit" value="Search">
        </form>
        {% block content %}{% endblock %}
    </body>
</html>

photos.html:

{% extends 'index.html' %}
{% block error %}
    {% if error %}
        <p> {{ error}} </p>
    {% endif %}
{% endblock %}

{% block content %}
    {% if photos %}
        {% for photo in photos %}
            {{ photo }}
        {% endfor %}
    {% endif %}
{% endblock%}

url.py:

urlpatterns = patterns('',
    (r'', index),
    (r'^time/$', current_datetime),
    (r'^photos/(\w+)$', photos)
)

我甚至尝试过加上 {% csrf_token %},但还是没用

谢谢你

更新
我在日志中看到了这些信息

UserWarning: A {% csrf_token %} was used in a template, but the context did not provide the value.  This is usually caused by not using RequestContext.
  warnings.warn("A {% csrf_token %} was used in a template, but the context did not provide the value.  This is usually caused by not using RequestContext.")  

这是在我给 render_to_response() 加上 context_instance=RequestContext(request) 之后出现的

7 个回答

3

这里有几个需要排查的问题:

  • 请在网页浏览器中打开你的“index”页面,然后选择“查看源代码”,检查一下 {% csrf_token %} 是否被正确替换。它应该变成一个 <input> 标签。如果没有替换成功,那说明你的 index 页面有问题。如果替换成功了,那就说明你的照片页面有问题。

  • index.html 中的 POST URL 和 urls.py 中的模式不匹配。你的 urls.py 似乎是希望搜索词作为 URL 的一部分,但实际上你是把它作为 HTTP POST 参数发送的。你需要通过 request.POST 来获取它。

5

假设你正在使用一个比较新的Django版本(1.3/1.4/dev),你可以按照以下步骤操作:

  • settings.py 文件中,把中间件 django.middleware.csrf.CsrfViewMiddleware 加入到 MIDDLEWARE_CLASSES 列表里。
  • 在你的模板中,表单里要使用 {% crsf_token %}
  • 在你的视图中,确保使用了 django.core.context_processors.csrf 这个上下文处理器,可以通过以下方式实现:
    • 使用 RequestContext,这个来自 django.template
    • 直接从 from django.core.context_processors 导入csrf处理器

示例

from django.template import RequestContext
from django.shortcuts import render_to_response

def my_view(request):
    return render_to_response('my_template.html', {}, context_instance=RequestContext(request))

或者

from django.core.context_processors import csrf
from django.shortcuts import render_to_response

def my_view(request):
    c = {csrf(request)}
    return render_to_response('my_template.html', c)

参考资料

(这是为了将来和后来的观众留下的详细帖子)

9

在你每个会用到表单的视图里,都要加上 context_instance=RequestContext(request) 这一行代码:

return render_to_response('index.html', {}, context_instance=RequestContext(request) )


return render_to_response('photos.html', {'photos': photos}, context_instance=RequestContext(request) )

撰写回答