Wednesday, October 16, 2019

Resetting password views

In the previous post we saw how to change the password. Sometimes users forget their passwords and thus applications provide a password reset facility to help them out in such cases. In this post we'll see how to implement password reset facility.

Add the following URL patterns for password restoration to the urls.py file of the account application:

#reset password urls
path('password_reset/',
auth_views.PasswordResetView.as_view(),
name='password_reset'),
path('password_reset/done/',
auth_views.PasswordResetDoneView.as_view(),
name='password_reset_done'),
path('reset/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(),
name='password_reset_confirm'),
path('reset/done/',
auth_views.PasswordResetCompleteView.as_view(),
name='password_reset_complete'),


Next add a new file in the templates/registration/ directory of your account application and name it password_reset_form.html. Add the following code to it:

{% extends "base.html" %}
{% block title %}Reset your password{% endblock %}
{% block content %}
<h1>Forgotten your password?</h1>
<p>Enter your e-mail address to obtain a new password.</p>
<form action="." method="post">
{{ form.as_p }}
<p><input type="submit" value="Send e-mail"></p>
{% csrf_token %}
</form>
{% endblock %}


Now, create another file in the same directory and name it password_reset_email.html. Add the following code to it:

Someone asked for password reset for email {{ email }}. Follow the link
below:
{{ protocol }}://{{ domain }}{% url "password_reset_confirm" uidb64=uid
token=token %}
Your username, in case you've forgotten: {{ user.get_username }}


The password_reset_email.html template will be used to render the email sent to users to reset their password. Now create another file in the same directory and name it password_reset_done.html. Add the following code to it:

{% extends "base.html" %}
{% block title %}Reset your password{% endblock %}
{% block content %}
<h1>Reset your password</h1>
<p>We've emailed you instructions for setting your password.</p>
<p>If you don't receive an email, please make sure you've entered the address you registered with.</p>
{% endblock %}


Create another template in the same directory and name it password_reset_confirm.html. Add the following code to it:

{% extends "base.html" %}
{% block title %}Reset your password{% endblock %}
{% block content %}
<h1>Reset your password</h1>
{% if validlink %}
<p>Please enter your new password twice:</p>
<form action="." method="post">
{{ form.as_p }}
{% csrf_token %}
<p><input type="submit" value="Change my password" /></p>
</form>
{% else %}

<p>The password reset link was invalid, possibly because it has
already been used. Please request a new password reset.</p>
{% endif %}
{% endblock %}

In the above code we check whether the provided link is valid. The view PasswordResetConfirmView sets this variable and puts it in the context of the password_reset_confirm.html template. If the link is valid, we display the user password reset form.

Create another template and name it password_reset_complete.html. Enter the following code into it:

{% extends "base.html" %}
{% block title %}Password reset{% endblock %}
{% block content %}
<h1>Password set</h1>
<p>Your password has been set. You can <a href="{% url "login" %}">log in
now</a></p>
{% endblock %}


Finally, edit the registration/login.html template of the account application, and add the following code after the <form> element:

<p><a href="{% url "password_reset" %}">Forgotten your password?</a></p>

Now, open http://127.0.0.1:8000/account/login/ in your browser and click on the Forgotten your password? link. You should see the following page:








At this point, you need to add an SMTP configuration to the settings.py file of your project so that Django is able to send emails. However, during development, you can configure Django to write emails to the standard output instead of sending them through an SMTP server.

Django provides an email backend to write emails to the console. Edit the settings.py file of your project, and add the following line:

EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

The EMAIL_BACKEND setting indicates the class to use to send emails. Return to your browser, enter the email address of an existing user, and click on the SEND E-MAIL button. You should see the following page:





Take a look at the console where you are running the development server. You will see the generated email, as follows:

Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: Password reset on 127.0.0.1:8000
From: webmaster@localhost
To: user@domain.com
Date: Fri, 15 Dec 2017 14:35:08 -0000
Message-ID: <20150924143508.62996.55653@zenx.local>
Someone asked for password reset for email user@domain.com. Follow the link
below:
http://127.0.0.1:8000/account/reset/MQ/45f-9c3f30caafd523055fcc/
Your username, in case you've forgotten: zenx



The email is rendered using the password_reset_email.html template we created earlier. The URL to reset your password includes a token that was generated dynamically by Django. Copy the URL and open it in your browser. You should see the following page:



The page to set a new password corresponds to the password_reset_confirm.html template. Fill in a new password and click on the CHANGE MY PASSWORD button. Django creates a new encrypted password and saves it in the database. You will see the following success page:





Now, you can log back into your account using your new password. Each token to set a new password can be used only once. If you open the link you received again, you will get a message stating that the token is invalid.

In this post you have integrated the views of the Django authentication framework in your project. These views are suitable for most cases. However, you can create your own views if you need a different behavior.

Django also provides the authentication URL patterns we just created. You can comment out the authentication URL patterns we added to the urls.py file of the account application and include
django.contrib.auth.urls instead, as follows:

from django.urls import path, include
# ...
urlpatterns = [
# ...
path('', include('django.contrib.auth.urls')),

Here I'm ending this post. In the next post we'll build a view to allow visitors to create a user account.
Share:

0 comments:

Post a Comment