我一直在使用Django开发一个网站,我正在尝试基于我的应用程序中的一个模型实现一个简单的表单。我有一些问题让它工作,但我目前的主要问题是我一直收到以下错误:CSRF令牌丢失或不正确。
我正在使用python 2.7运行Django 1.6。
我已经查看过以下帖子以尝试修复我的问题(以及我在适当情况下提供上下文引用的各种其他解决方案),但它对我没用:
Django: CSRF token missing or incorrect - 基本上,将RequestContext
和render_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/" ...>
引用的函数相同。
非常感谢您对此问题的任何帮助。
答案 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。