Django 1.8 表单错误后没有 CSRF 令牌
No CSRF token after Django 1.8 form error
我最近将我的网站升级到 Django 1.8,当我的注册(用户注册)表格发布时,我得到了 "ImportError No module named lib"。具体来说,如果用户正在注册帐户并且他们的密码不匹配,我的 form 将显示错误。如果他们随后输入匹配的密码,我会收到以下 Django 错误:
Request Method: POST
Request URL: http://localhost:8000/create_account/
Django Version: 1.8.4
Python Version: 2.7.5
Installed Applications:
['django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'account',
'home',
'members',
'profile']
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware')
Traceback:
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
125. response = middleware_method(request, callback, callback_args, callback_kwargs)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/middleware/csrf.py" in process_view
189. return self._reject(request, REASON_BAD_TOKEN)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/middleware/csrf.py" in _reject
101. return _get_failure_view()(request, reason=reason)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/middleware/csrf.py" in _get_failure_view
33. return get_callable(settings.CSRF_FAILURE_VIEW)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/utils/lru_cache.py" in wrapper
101. result = user_function(*args, **kwds)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/core/urlresolvers.py" in get_callable
112. if submod and not module_has_submodule(import_module(parentmod), submod):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py" in import_module
37. __import__(name)
Exception Type: ImportError at /create_account/
Exception Value: No module named lib
正如您从堆栈跟踪中看到的那样,当使用匹配的密码发布表单时,在控制返回到显示表单的 create_account 视图之前,中间件将响应视为无效。我在urlresolvers.py模块下了断点,发现找不到的模块是"lib.local_csrf"。我应该补充一点,表单本身由登录(身份验证)表单和相关的注册(注册)表单组成,并且两种表单都包含 csrf_token 标签:
# home/templates/home.html
<form action="{% url 'sign-in' %}" method="post">
{% csrf_token %}
<!-- error fields appear here -->
{% for field in sign_in_form.visible_fields %}
{{ field.label_tag }}
{{ field }}
<input type="submit" value="Sign in">
<a href="#">Forgot password?</a>
</form>
<form action="{% url 'create-account' %}" method="post">
{% csrf_token %}
<!-- error fields appear here -->
{% for field in create_account_form.visible_fields %}
{{ field.label_tag }}
{{ field }}
{% endfor %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
<input type="submit" value="Sign up">
</form>
这是 create_account 视图:
# account/views.py
def create_account(request, template):
# Initialize the signin form on the same page.
sign_in_form = SignInAuthenticationForm(request, label_suffix="")
if request.method == "POST":
create_account_form = CreateAccountForm(request.POST, label_suffix="")
if create_account_form.is_valid():
user = User.objects.create_user(
username = create_account_form.cleaned_data['username'],
password = create_account_form.cleaned_data['password1']
)
# Create a new account.
account = Account(user=user)
account.save()
# Do other stuff and then redirect user to next form
else:
create_account_form = CreateAccountForm(label_suffix="")
return render_to_response(template, locals())
最有趣的是,当我在django.middleware.csrf中的process_view中设置断点时,csrf_token和request_csrf_token变量都包含相同的值时用户最初使用不匹配的密码提交表单。但是当他们输入匹配的密码并第二次重新提交表单时,csrf_token 包含令牌值但 request_csrf_token 为空。当用户重新提交表单时,request.POST['csrfmiddlewaretoken'] 不在 request.POST 字典中这一事实证实了这一点。我不明白为什么会这样。
此表单在 Django 1.6 中运行良好,但在 1.8(或可能是 1.7)中停止运行。我查看了 1.7 和 1.8 的发行说明,没有发现 CSRF 功能有任何变化。我还阅读了与 CSRF 有关的模板文档,但没有看到任何新内容。对此错误进行在线搜索也没有找到任何结果。
我怀疑你们中的一些人会建议我使用 django-registration-redux 库。由于我的注册工作流程,我认为我无法使用它。你看,用户在这个表单上注册后,他们首先被重定向到一个页面,当他们输入他们的用户个人资料时,然后是一个他们可以上传照片的页面,然后是一个页面来审查和批准他们的个人资料和照片.之后,它们被转发到我的支付处理器。如果我的付款处理商告诉我他们的付款方式已获批准,他们才真正注册了有效帐户。
谢谢。
实际错误 No module named lib
似乎是因为 Django 无法导入您在设置中指定的 CSRF_FAILURE_VIEW
。您可以尝试从您的设置中删除它,然后 Django 应该显示默认的 CSRF 失败页面而不是错误。我不知道导入失败的原因,因为您没有显示 CSRF_FAILURE_VIEW
或您的项目结构。
要修复 CSRF 错误,请尝试使用 render
快捷方式而不是 render_to_response
。它使用请求上下文呈现模板,以便 csrf_token 标记起作用。
# avoid locals() if possible!
return render(request, template, {...})
我最近将我的网站升级到 Django 1.8,当我的注册(用户注册)表格发布时,我得到了 "ImportError No module named lib"。具体来说,如果用户正在注册帐户并且他们的密码不匹配,我的 form 将显示错误。如果他们随后输入匹配的密码,我会收到以下 Django 错误:
Request Method: POST
Request URL: http://localhost:8000/create_account/
Django Version: 1.8.4
Python Version: 2.7.5
Installed Applications:
['django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'account',
'home',
'members',
'profile']
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware')
Traceback:
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
125. response = middleware_method(request, callback, callback_args, callback_kwargs)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/middleware/csrf.py" in process_view
189. return self._reject(request, REASON_BAD_TOKEN)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/middleware/csrf.py" in _reject
101. return _get_failure_view()(request, reason=reason)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/middleware/csrf.py" in _get_failure_view
33. return get_callable(settings.CSRF_FAILURE_VIEW)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/utils/lru_cache.py" in wrapper
101. result = user_function(*args, **kwds)
File "/Users/me/venv/scores/lib/python2.7/site-packages/django/core/urlresolvers.py" in get_callable
112. if submod and not module_has_submodule(import_module(parentmod), submod):
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py" in import_module
37. __import__(name)
Exception Type: ImportError at /create_account/
Exception Value: No module named lib
正如您从堆栈跟踪中看到的那样,当使用匹配的密码发布表单时,在控制返回到显示表单的 create_account 视图之前,中间件将响应视为无效。我在urlresolvers.py模块下了断点,发现找不到的模块是"lib.local_csrf"。我应该补充一点,表单本身由登录(身份验证)表单和相关的注册(注册)表单组成,并且两种表单都包含 csrf_token 标签:
# home/templates/home.html
<form action="{% url 'sign-in' %}" method="post">
{% csrf_token %}
<!-- error fields appear here -->
{% for field in sign_in_form.visible_fields %}
{{ field.label_tag }}
{{ field }}
<input type="submit" value="Sign in">
<a href="#">Forgot password?</a>
</form>
<form action="{% url 'create-account' %}" method="post">
{% csrf_token %}
<!-- error fields appear here -->
{% for field in create_account_form.visible_fields %}
{{ field.label_tag }}
{{ field }}
{% endfor %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
<input type="submit" value="Sign up">
</form>
这是 create_account 视图:
# account/views.py
def create_account(request, template):
# Initialize the signin form on the same page.
sign_in_form = SignInAuthenticationForm(request, label_suffix="")
if request.method == "POST":
create_account_form = CreateAccountForm(request.POST, label_suffix="")
if create_account_form.is_valid():
user = User.objects.create_user(
username = create_account_form.cleaned_data['username'],
password = create_account_form.cleaned_data['password1']
)
# Create a new account.
account = Account(user=user)
account.save()
# Do other stuff and then redirect user to next form
else:
create_account_form = CreateAccountForm(label_suffix="")
return render_to_response(template, locals())
最有趣的是,当我在django.middleware.csrf中的process_view中设置断点时,csrf_token和request_csrf_token变量都包含相同的值时用户最初使用不匹配的密码提交表单。但是当他们输入匹配的密码并第二次重新提交表单时,csrf_token 包含令牌值但 request_csrf_token 为空。当用户重新提交表单时,request.POST['csrfmiddlewaretoken'] 不在 request.POST 字典中这一事实证实了这一点。我不明白为什么会这样。
此表单在 Django 1.6 中运行良好,但在 1.8(或可能是 1.7)中停止运行。我查看了 1.7 和 1.8 的发行说明,没有发现 CSRF 功能有任何变化。我还阅读了与 CSRF 有关的模板文档,但没有看到任何新内容。对此错误进行在线搜索也没有找到任何结果。
我怀疑你们中的一些人会建议我使用 django-registration-redux 库。由于我的注册工作流程,我认为我无法使用它。你看,用户在这个表单上注册后,他们首先被重定向到一个页面,当他们输入他们的用户个人资料时,然后是一个他们可以上传照片的页面,然后是一个页面来审查和批准他们的个人资料和照片.之后,它们被转发到我的支付处理器。如果我的付款处理商告诉我他们的付款方式已获批准,他们才真正注册了有效帐户。
谢谢。
实际错误 No module named lib
似乎是因为 Django 无法导入您在设置中指定的 CSRF_FAILURE_VIEW
。您可以尝试从您的设置中删除它,然后 Django 应该显示默认的 CSRF 失败页面而不是错误。我不知道导入失败的原因,因为您没有显示 CSRF_FAILURE_VIEW
或您的项目结构。
要修复 CSRF 错误,请尝试使用 render
快捷方式而不是 render_to_response
。它使用请求上下文呈现模板,以便 csrf_token 标记起作用。
# avoid locals() if possible!
return render(request, template, {...})