Django csrf令牌丢失或错误不正确

时间:2014-07-19 17:46:02

标签: django csrf django-csrf

我一直在使用Django开发一个网站,我正在尝试基于我的应用程序中的一个模型实现一个简单的表单。我有一些问题让它工作,但我目前的主要问题是我一直收到以下错误:CSRF令牌丢失或不正确。

我正在使用python 2.7运行Django 1.6。

我已经查看过以下帖子以尝试修复我的问题(以及我在适当情况下提供上下文引用的各种其他解决方案),但它对我没用:

Django: CSRF token missing or incorrect - 基本上,将RequestContextrender_to_response一起传递回来。

CSRF Token missing or incorrect - 我已确保django.middleware.csrf.CsrfViewMiddleware文件中出现settings.py,并且我已尝试按照TEMPLATE_CONTEXT_PROCESSORS设置的指示添加django.core.context_processors.csrf,但没有更改。当我在shell中检查这些设置时,我得到以下输出:

> from django.conf import settings
> settings.TEMPLATE_CONTEXT_PROCESSORS
('django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug', 'django.core.context_processors.i18n',
'django.core.context_processors.media', 'django.core.context_processors.static',
'django.core.context_processors.tz',
'django.contrib.messages.context_processors.messages')

我将以下代码放在我的settings.py文件中,但是我继续得到403 CSRF令牌错误:

import django.conf.global_settings as DEFAULT_SETTINGS

TEMPLATE_CONTEXT_PROCESSORS = DEFAULT_SETTINGS.TEMPLATE_CONTEXT_PROCESSORS + (
    'django.core.context_processors.csrf',
)

我也遵循了错误消息本身给出的建议,即使用RequestContext而不是Context,确保我有{%csrf_token%}标签。

来自我的views.py文件:

from django.shortcuts import render
from django.views.decorators.csrf import csrf_protect, csrf_exempt
from django.template import loader, Context
from django.http import HttpResponse
from forms import StudentForm
from django.http import HttpResponseRedirect
from django.core.context_processors import csrf
from django.template import RequestContext

def edit(request):
form = StudentForm(request.POST or None)
if form.is_valid():
    form.save()
    return Redirect('/myprofile/')
return render(request, 'myprofile.html',{'form':form})

请注意,我已经阅读了其他一些修复此问题的指南,其中涉及以几种不同的方式包含RequestContext:return render_to_response('myprofile.html', RequestContext(request, {}))return render_to_response('myprofile.html', RequestContext(request)),但这些都不适用于我。

我的settings.py文件:

import django.conf.global_settings as DEFAULT_SETTINGS

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myprofile',
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)


TEMPLATE_CONTEXT_PROCESSORS = DEFAULT_SETTINGS.TEMPLATE_CONTEXT_PROCESSORS + (
    'django.core.context_processors.csrf',
)

我的HTML代码如下:

<form action = "/myprofile/" method = "post"> {% csrf_token %}
  <ul>
  {{ form.as_ul }}
  </ul>

  <input type = "submit" name = "Submit" value = "Edit Form">
</form>

请注意,我还尝试将令牌添加为隐藏输入,但这并没有解决我的问题。生成此视图的函数也与表单的操作<form action = "/myprofile/" ...>引用的函数相同。

非常感谢您对此问题的任何帮助。

2 个答案:

答案 0 :(得分:4)

你的问题在这里:

return render_to_response('myprofile.html',{},RequestContext(request))

虽然您已添加了csrf:

c = {}
c.update(csrf(request))

您对c没有任何操作。要一劳永逸地解决这个问题,只需使用render shortcut

from django.shortcuts import render, redirect

def edit(request):
     form = StudentForm(request.POST or None)
     if form.is_valid():
        form.save()
        return redirect('/myprofile/')
     return render(request, 'myprofile.html', {'form': form})

接下来,在您的模板中,您只使用{% csrf_token %}而不是{{ csrf_token }}。标签将呈现表单字段。

答案 1 :(得分:2)

{{csrf_token}} 似乎为空,并覆盖由 {%csrf_token%} 生成的隐藏输入字段。只需从模板中删除 {{csrf_token}} 隐藏的输入字段,它就可能正常工作。

此外,当您使用 RequestContext 时,您不必手动将CSRF令牌添加到模板中,因此您可以从视图中删除以下代码。

c = {}
c.update(csrf(request))

有关详细信息,请参阅https://docs.djangoproject.com/en/1.6/ref/contrib/csrf/#how-csrf-works