【问题标题】:Password Reset Confirm don`t work密码重置确认不起作用
【发布时间】: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&lt;uidb64&gt;[0-9A-Za-z]+)/(?P&lt;token&gt;.+)/$' 更改为 '^password-reset-confirm/(?P&lt;uidb64&gt;[0-9A-Za-z]+)-(?P&lt;token&gt;.+)/$'?
  • 我昨天都试过了,结果和我之前在帖子中描述的一样,但现在当我尝试时,它在日志中出现了错误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&lt;uidb64&gt;[0-9\u200c\u200bA-Za-z]+)-(?P&lt;token&gt;.\u200c\u200b+)/$'],我真的很困惑。请帮忙!
  • 我也试过这个'^password-reset-confirm/(?P&lt;uidb64&gt;[-\w]+)-(?P&lt;token&gt;[-\w]+)/$',但结果是一样的。你有什么建议给我@an0o0nym ?

标签: python django python-3.x django-views django-1.9


【解决方案1】:

我遇到了同样的问题,然后我删除了自定义 ResetPasswordRequestView 视图并使用了 django 框架提供的默认视图。您需要做的就是创建一个名为registration/password_reset.html 的模板并编写如下网址:

from django.contrib.auth import view as auth_view 
url(r'^password-reset/$', auth_view.ResetPasswordRequestView.as_view(),{'template_name':'registration/password_reset.html'} name="reset_password")

您也可以对其他 url 执行相同操作。您可以找到我们正在调用的 ResetPasswordRequestView 的代码。 here

【讨论】:

    猜你喜欢
    • 2019-12-01
    • 2020-01-15
    • 1970-01-01
    • 2021-02-22
    • 2016-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-06
    相关资源
    最近更新 更多