无法将重置电子邮件链接路由到密码重置视图

时间:2016-10-29 17:33:55

标签: python django model-view-controller django-templates django-views

我正在通过django中的电子邮件重置密码。我已经正确发送了包含密码重置链接的电子邮件,问题是当用户点击电子邮件中的密码重置链接时,正被重定向到"发送重置链接到邮件"而不是"输入新密码链接"。

Url&#39>如下:

 url(r'^login/$', views.Login, name='login'),
 url(r'^register/$', views.Register.as_view(),  name='register'),
 url(r'^reset_password', views.ResetPasswordRequestView.as_view(), name="password_reset"),
 url(r'^reset_password_confirm/(?P<uidb64>[0-9A-Za-z]+)-(?P<token>.+)/$', views.PasswordResetConfirmView.as_view(), name='reset_password_confirm'),

用户用来输入他的电子邮件的模板就是这个(为了简洁起见,在模板和条带的基础内使用):

<form action="" method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <input type="submit" value="Submit"/>
</form>

处理发送密码重置链接的视图:

class ResetPasswordRequestView(FormView):
template_name = 'authentication/password_reset.html'
success_url = 'login'
form_class = PasswordResetRequestForm

def get(self, request, *args, **kwargs):
    form = PasswordResetRequestForm()
    return render(request, 'authentication/password_reset.html', {'form': form})

def post(self, request, *args, **kwargs):
    '''
    A normal post request which takes input from field "email" (in ResetPasswordRequestForm).
    '''
    form = self.form_class(request.POST)
    form_email = ''
    if form.is_valid():
        form_email = form.cleaned_data["email"]
    if self.validate_email_address(form_email):  # uses the method written above
        '''
        Verifies that the submited email is valid and gets its asociated user. If it is registered an
        email will be sent to that address with the reset link
        '''
        user = User.objects.get(email=form_email)
        if user is not None:
            email_template_data = {
                'email': user.email,
                'domain': request.META['HTTP_HOST'],
                'site_name': 'Collector',
                'uid': urlsafe_base64_encode(force_bytes(user.pk)),
                'user': user,
                'token': default_token_generator.make_token(user),
                'protocol': 'http',
            }
            email_template_name = 'authentication/password_reset_email.html'
            subject = 'Password reset on Collector'
            email = loader.render_to_string(email_template_name, email_template_data)

            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 ' + form_email + ". Please check its inbox to continue reseting password.")
            return result
        else:
            result = self.form_invalid(form)
            messages.error(request, 'No user is associated with this email address')
            return result

    messages.error(request, 'Invalid Input')
    return self.form_invalid(form)

处理输入密码的视图如下:

class PasswordResetConfirmView(FormView):
"""
    View that checks the hash in a password reset link and presents a
    form for entering a new password.
"""
template_name = "authentication/password_reset_enter_new.html"
success_url = 'login'
form_class = SetPasswordForm

def get(self, request, uidb64=None, token=None, *arg, **kwargs):
    form = SetPasswordForm()
    return render(request, "authentication/password_reset_enter_new.html", {'form': form})

def post(self, request, uidb64=None, token=None, *arg, **kwargs):

    UserModel = User
    form = self.form_class(request.POST)
    assert uidb64 is not None and token is not None  # checked by URLconf
    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_password']
            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)

我的问题是发送给用户的网址没有路由到PasswordResetConfirmView,这个网址如下:

127.0.0.1:8000/authentication/reset_password_confirm/MQ-4gk-262cd9422172a2e21be1/

非常感谢任何帮助或输入!

1 个答案:

答案 0 :(得分:0)

您需要终止reset_password网址:

url(r'^reset_password/$', ...)

否则它将匹配开始所有字符串。

另请注意,Django已经内置了大部分功能。