【发布时间】:2020-02-18 06:48:02
【问题描述】:
这里我没有使用PasswordResetView,因为我通过我的动态电子邮件配置发送电子邮件,所以为此我制作了自己的视图,它使用PasswordResetTokenGenerator 生成令牌,并且还将电子邮件发送给用户。我电子邮件中的密码重置链接看起来像这样http://127.0.0.1:8000/password-reset/confirm/NQ/5as-b3502199950ff028a6ef/
但是在单击该链接后,它会重定向到 password_reset_confirm,这很好,但在此视图中,{{form.as_p}} 不起作用。它只显示按钮,但在使用 auth-views.PasswordresetView 之前,表单正在工作,但现在没有在模板中传递表单。
我该如何解决这个问题?
urls.py
path('password-reset/',views.send_password_reset_email,name='password_reset'),
path('password-reset/done/',auth_views.PasswordResetDoneView.as_view(template_name='password_reset_done.html'),name='password_reset_done'),
path('password-reset/confirm/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(template_name='password_reset_confirm.html', success_url=reverse_lazy('password_reset_complete'),),name='password_reset_confirm'),
views.py
def send_password_reset_email(request):
form = CustomPasswordResetForm()
if request.method == 'POST':
form = CustomPasswordResetForm(request.POST)
if form.is_valid():
email = form.cleaned_data['email']
user = get_user_model().objects.get(email__iexact=email)
site = get_current_site(request)
mail_subject = "Password Reset on {} ".format(site.domain)
message = render_to_string('password_reset_email.html', {
"user": user,
'domain': site.domain,
'uid': urlsafe_base64_encode(force_bytes(user.pk)).decode(),
'token': activation_token.make_token(user)
})
config = EmailConfiguration.objects.order_by('-date').first()
backend = EmailBackend(host=config.email_host, port=config.email_port, username=config.email_host_user,
password=config.email_host_password, use_tls=config.email_use_tls)
email = EmailMessage(subject=mail_subject, body=message, from_email=config.email_host_user, to=[user.email],
connection=backend)
email.send()
return redirect('password_reset_done')
return render(request, 'password_reset.html',{'form':form})
password_reset_email.html
{% block reset_link %}
http://{{domain}}{% url 'password_reset_confirm' uidb64=uid token=token %}
{% endblock %}
password_reset_confirm.html
<form action="" method="post">
{% csrf_token %}
{{form.as_p}}
<button type="submit" class="btn btn-info">Reset Password</button>
</form>
tokens.py
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.utils import six
class TokenGenerate(PasswordResetTokenGenerator):
def _make_hash_value(self, user, timestamp):
return (
six.text_type(user.id)+six.text_type(timestamp)+six.text_type(user.is_active)
)
activation_token=TokenGenerate()
【问题讨论】:
-
看
PasswordResetConfirmView的出处。如果self.validlink == False,它将context['form']设置为None。尝试在模板中打印{{ title }},它可能会显示“密码重置失败”。似乎找不到具有正确 ID 的用户。 -
你不应该在你的 uid 末尾有
.decode()。 -
@dirkgroten 你说得对,它说
password reset unsuccessful我也删除了.decode。那么如何解决这个问题? -
在你的 django shell 中,尝试:
uid = force_text(urlsafe_base64_decode(uidb64))然后User.objects.get(pk=uid)。 -
另外,请确保您使用与
PasswordResetConfirmView相同的token_generator,我看不出您从哪里导入activation_token,但它可能是错误的。再次,查看 Django 源代码来做同样的事情。