【发布时间】:2016-12-22 00:05:30
【问题描述】:
密码重置成功后(第一步)我的电子邮件中有消息,下一个重定向链接指向下一步:
127.0.0.1:8000/en/account/password-reset-confirm/NA-4ei-53e725f1ba4cbfc54fb8/
不幸的是,我在 password_reset_confirm.html 模板中总是有这个 消息:
密码重置链接无效,可能是因为它已经 被使用。请申请重设新密码。
问题:我做错了什么?!
urls.py
url(r'^password-reset/$',
ResetPasswordRequestView.as_view(),
name="reset_password"),
url(r'^password-reset-confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$',
PasswordResetConfirmView.as_view(),
name='reset_password_confirm'),
views.py
class ResetPasswordRequestView(FormView):
template_name = "registration/password_reset.html"
success_url = '/account/password-reset'
form_class = PasswordResetRequestForm
@staticmethod
def validate_email_address(email):
try:
validate_email(email)
return True
except ValidationError:
return False
def post(self, request, *args, **kwargs):
form = self.form_class(request.POST)
try:
if form.is_valid():
data = form.cleaned_data["email_or_username"]
if self.validate_email_address(data) is True:
associated_users = User.objects.filter(Q(email=data) | Q(username=data))
if associated_users.exists():
for user in associated_users:
c = {
'email': user.email,
'domain': request.META['HTTP_HOST'],
'site_name': _('Requirements Management System'),
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'user': user,
'token': default_token_generator.make_token(user),
'protocol': 'http',
}
subject_template_name = 'registration/password_reset_subject.txt'
email_template_name = 'registration/password_reset_email.html'
subject = loader.render_to_string(subject_template_name, c)
subject = ''.join(subject.splitlines())
email = loader.render_to_string(email_template_name, c)
send_mail(subject, email, DEFAULT_FROM_EMAIL, [user.email], fail_silently=False)
result = self.form_valid(form)
messages.success(request, 'An email has been sent to ' +
data + ". Please check its inbox to continue reseting password.")
return result
result = self.form_invalid(form)
messages.error(request, _('No user is associated with this email address'))
return result
else:
associated_users = User.objects.filter(username=data)
if associated_users.exists():
for user in associated_users:
c = {
'email': user.email,
'domain': '127.0.0.1:8000',
'site_name': _('Requirements Management System'),
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'user': user,
'token': default_token_generator.make_token(user),
'protocol': 'http',
}
subject_template_name = 'registration/password_reset_subject.txt'
email_template_name = 'registration/password_reset_email.html'
subject = loader.render_to_string(subject_template_name, c)
# Email subject *must not* contain newlines
subject = ''.join(subject.splitlines())
email = loader.render_to_string(email_template_name, c)
send_mail(subject, email, DEFAULT_FROM_EMAIL, [user.email], fail_silently=False)
result = self.form_valid(form)
messages.success(request, 'Email has been sent to ' +
data + "'s email address. Please check its inbox to continue reseting password.")
return result
result = self.form_invalid(form)
messages.error(request, _('This username does not exist in the system.'))
return result
except Exception as e:
print(e)
return self.form_invalid(form)
class PasswordResetConfirmView(FormView):
template_name = "registration/password_reset_confirm.html"
success_url = '/account/password-reset-confirm/'
form_class = SetPasswordForm
def post(self, request, uidb64=None, token=None, *arg, **kwargs):
UserModel = get_user_model()
form = self.form_class(request.POST)
assert uidb64 is not None and token is not None
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):
if form.is_valid():
new_password = form.cleaned_data['new_password2']
user.set_password(new_password)
user.save()
messages.success(request, 'Password has been reset.')
return self.form_valid(form)
else:
messages.error(request, 'Password reset has not been unsuccessful.')
return self.form_invalid(form)
else:
messages.error(request, 'The reset password link is no longer valid.')
return self.form_invalid(form)
forms.py
class PasswordResetRequestForm(forms.Form):
email_or_username = forms.CharField(required=True,
widget=TextInput(attrs={'placeholder': _('Email address or Username')}))
class SetPasswordForm(forms.Form):
error_messages = {
'password_mismatch': _("The two password fields didn't match."),
}
new_password1 = forms.CharField(
widget=forms.PasswordInput(attrs={'placeholder': _('Enter your new password')}))
new_password2 = forms.CharField(
widget=forms.PasswordInput(attrs={'placeholder': _('Enter your new password one more time')}))
def clean_new_password2(self):
first_password = self.cleaned_data.get('new_password1')
second_password = self.cleaned_data.get('new_password2')
if first_password and second_password:
if first_password != second_password:
raise forms.ValidationError(self.error_messages['password_mismatch'], code='password_mismatch')
return second_password
password_reset.html
<form action="." class="form" method="post">
{% csrf_token %}
{{ form.email_or_username }}
<button type="submit" class="button">Send e-mail</button>
</form>
【问题讨论】:
-
你能告诉我们你的
PasswordResetRequestForm和registration/password_reset.html吗? -
我认为这些文件中没有什么异常,但无论如何我更新了我的帖子,请检查一下。你有什么想法吗?!
-
您的网址格式似乎有问题。您正在生成的与模式不匹配。您是否尝试将
'^password-reset-confirm/(?P<uidb64>[0-9A-Za-z]+)/(?P<token>.+)/$'更改为'^password-reset-confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$'? -
我昨天都试过了,结果和我之前在帖子中描述的一样,但现在当我尝试时,它在日志中出现了错误
Reverse for 'reset_password_confirm' with arguments '()' and keyword arguments '{'uidb64': b'NA', 'token': '4ei-53e725f1ba4cbfc54fb8'}' not found. 1 pattern(s) tried: ['en/account/password-reset-confirm/(?P<uidb64>[0-9\u200c\u200bA-Za-z]+)-(?P<token>.\u200c\u200b+)/$'],我真的很困惑。请帮忙! -
我也试过这个
'^password-reset-confirm/(?P<uidb64>[-\w]+)-(?P<token>[-\w]+)/$',但结果是一样的。你有什么建议给我@an0o0nym ?
标签: python django python-3.x django-views django-1.9