You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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替代自定义函数视图,减少重复代码。

验证步骤

  1. 修复模板变量引用
  2. 替换自定义表单为继承内置的版本
  3. 重新发送密码重置邮件,点击链接验证表单是否正常显示
  4. 测试密码重置流程是否完整

内容的提问来源于stack exchange,提问作者tiberhockey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 11:10:23