Django自定义密码重置确认模板表单不显示问题求助
密码重置确认页面表单不显示问题修复
问题现象
密码重置初始页面修改正常,但点击邮件中的重置链接后,确认页面仅加载<h1>等静态元素,自定义密码输入表单未显示。
问题代码分析
HTML模板(users/password_reset_confirm.html)
{% load static %} <div class="box" align="center"> <h1>Write your new password</h1> <div class="small-line"></div> <form method="POST"> {% csrf_token %} {{ context.as_p }} <button type="submit" class="sendbut">Reset Password</button> </form> </div>
forms.py
class SetPasswordForm(forms.Form): def __init__(self, *args, **kwargs): super(SetPasswordForm, self).__init__(*args, **kwargs) # … new_password1 = forms.CharField( label=("New password"), widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}), strip=False, help_text=password_validation.password_validators_help_text_html(), ) new_password2 = forms.CharField( label=("New password confirmation"), strip=False, widget=forms.PasswordInput(attrs={'autocomplete': 'new-password'}), )
views.py
@sensitive_post_parameters() @never_cache def PasswordResetConfirmView(request, uidb64=None, token=None, template_name='users/password_reset_confirm.html', token_generator=default_token_generator, set_password_form=SetPasswordForm, post_reset_redirect=None, current_app=None, extra_context=None): """ View that checks the hash in a password reset link and presents a form for entering a new password. """ UserModel = get_user_model() assert uidb64 is not None and token is not None # checked by URLconf if post_reset_redirect is None: post_reset_redirect = reverse('password_reset_complete') else: post_reset_redirect = resolve_url(post_reset_redirect) try: # urlsafe_base64_decode() decodes to bytestring on Python 3 uid = force_str(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 token_generator.check_token(user, token): validlink = True title = ('Enter new password') if request.method == 'POST': form = set_password_form(user, request.POST) if form.is_valid(): form.save() return HttpResponseRedirect(post_reset_redirect) else: form = set_password_form(user) else: validlink = False form = None title = ('Password reset unsuccessful') context = { 'form': form, 'title': title, 'validlink': validlink, } if extra_context is not None: context.update(extra_context) if current_app is not None: request.current_app = current_app return TemplateResponse(request, template_name, context)
urls.py
urlpatterns = [ path('password_reset/', views.password_reset, name='password_reset'), path('password_reset/done/', views.password_reset_done, name="password_reset_done"), path(r'reset/<uidb64>/<token>/', views.PasswordResetConfirmView, name='password_reset_confirm'), ]
核心问题与修复方案
1. 模板变量引用错误(最直接原因)
模板中错误使用{{ context.as_p }}调用表单,但视图传递的上下文变量名是form,而非context。修改模板中的表单渲染代码:
<!-- 替换原有的 {{ context.as_p }} --> {{ form.as_p }}
2. 自定义SetPasswordForm存在缺陷
- 未接收
user参数:视图初始化表单时传入了user对象,但自定义表单的__init__方法未处理该参数,会导致初始化报错。 - 缺少
save()方法:视图中调用form.save()保存密码,但自定义表单未实现该方法。
修复方案:直接继承Django内置的SetPasswordForm(推荐),避免重复造轮子:
from django.contrib.auth.forms import SetPasswordForm as BaseSetPasswordForm class SetPasswordForm(BaseSetPasswordForm): # 仅保留自定义样式或逻辑,无需重写核心字段和方法 def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 自定义字段属性,比如添加autocomplete self.fields['new_password1'].widget.attrs.update({'autocomplete': 'new-password'}) self.fields['new_password2'].widget.attrs.update({'autocomplete': 'new-password'})
3. 视图逻辑优化(可选)
- 当
validlink=False时,建议在模板中添加错误提示,避免用户困惑。 - 可以使用Django类视图
PasswordResetConfirmView替代自定义函数视图,减少重复代码。
验证步骤
- 修复模板变量引用
- 替换自定义表单为继承内置的版本
- 重新发送密码重置邮件,点击链接验证表单是否正常显示
- 测试密码重置流程是否完整
内容的提问来源于stack exchange,提问作者tiberhockey
相关产品推荐
相关产品推荐

