Django1.6自定义密码重置确认表单与视图报错排查
我来帮你一步步解决遇到的两个核心问题:SetPasswordForm无set_cookie属性错误,以及完成整个密码重置确认流程。
一、解决'SetPasswordForm' object has no attribute 'set_cookie'错误
这个错误的根源在于视图配置和请求处理逻辑的几个小问题,我们逐个修正:
1. 修正success_url配置
你当前把success_url设为模板路径(registration/password_reset_complete.html),这是错误的——FormView的success_url需要指向URL路径或URL名称,而非模板文件。
首先在urls.py中添加密码重置完成页的URL配置:
from django.views.generic.base import TemplateView url(r'^account/password_reset_complete/$', TemplateView.as_view(template_name='registration/password_reset_complete.html'), name='password_reset_complete'),
然后在PasswordResetConfirmView中用reverse_lazy获取这个URL:
from django.core.urlresolvers import reverse_lazy class PasswordResetConfirmView(FormView): template_name = "registration/password_reset_confirm.html" success_url = reverse_lazy('password_reset_complete') # 替换原来的模板路径 form_class = SetPasswordForm # ... 其他代码保持不变
2. 替换form_valid的调用逻辑
你已经手动完成了密码保存的逻辑,不需要依赖FormView默认的form_valid方法。在post方法的form.is_valid()分支里,把return self.form_valid(form)改成直接返回重定向响应:
return HttpResponseRedirect(self.get_success_url())
这能避免FormView内部可能的错误调用,也符合你已经完成表单处理的逻辑。
3. 处理GET请求的token验证
用户点击重置链接是GET请求,你当前只在POST方法中验证token,导致未验证就显示表单。给视图添加get方法,先验证链接有效性再显示表单:
from django.core.urlresolvers import reverse def get(self, request, uidb64=None, token=None, *args, **kwargs): UserModel = get_user_model() try: uid = urlsafe_base64_decode(uidb64) user = UserModel._default_manager.get(pk=uid) except (TypeError, ValueError, OverflowError, UserModel.DoesNotExist): user = None if user is not None and default_token_generator.check_token(user, token): # 链接有效,显示重置表单 return super(PasswordResetConfirmView, self).get(request, *args, **kwargs) else: # 链接无效,返回重置页面并提示错误 messages.error(request, 'The reset password link is no longer valid.') return HttpResponseRedirect(reverse('reset_password'))
二、解决Django 1.6无update_session_auth_hash的问题
Django 1.6没有内置的update_session_auth_hash方法,我们可以手动模拟这个功能,确保用户修改密码后当前session仍然有效,同时更新认证哈希值提升安全性。
在user.save()之后添加以下代码:
from django.contrib.auth import SESSION_KEY, BACKEND_SESSION_KEY, HASH_SESSION_KEY from django.contrib.auth import get_backends # 更新session中的用户认证信息 request.session[SESSION_KEY] = user._meta.pk.value_to_string(user) request.session[BACKEND_SESSION_KEY] = get_backends()[0].__class__.__name__ request.session[HASH_SESSION_KEY] = user.get_session_auth_hash()
这段代码和Django 1.7+的update_session_auth_hash功能一致,能避免用户修改密码后session失效的问题。
三、修正urls.py的其他错误
你当前的reset_password_doneURL指向了ResetPasswordRequestView,这是错误的——这个页面应该是显示“重置邮件已发送”的提示页,改成TemplateView:
url(r'^account/password/reset/done/$', TemplateView.as_view(template_name='registration/password_reset_done.html'), name="reset_password_done"),
完成以上修改后,你的自定义密码重置确认流程应该就能正常工作了:用户点击重置链接后先验证有效性,验证通过后显示密码重置表单,提交后保存新密码并更新session,最后跳转到重置完成页。
内容的提问来源于stack exchange,提问作者Kewin Rozz

