30
loading...
This website collects cookies to deliver better user experience
PasswordResetView
.PasswordResetView
- This view displays the form where the user will submit his/her email address -> checks if a user with the provided email address exists in the database or not -> generates a password reset link that is going to be used only once -> and finally sends that link to the user's email address.PasswordResetForm
class and customize it a bit.from django.urls import reverse_lazy
from django.contrib.auth.views import PasswordResetView
from django.contrib.messages.views import SuccessMessageMixin
class ResetPasswordView(SuccessMessageMixin, PasswordResetView):
template_name = 'users/password_reset.html'
email_template_name = 'users/password_reset_email.html'
subject_template_name = 'users/password_reset_subject'
success_message = "We've emailed you instructions for setting your password, " \
"if an account exists with the email you entered. You should receive them shortly." \
" If you don't receive an email, " \
"please make sure you've entered the address you registered with, and check your spam folder."
success_url = reverse_lazy('users-home')
template_name
- if not given any, django defaults to registration/password_reset_form.html to render the associated template for the view, but since our template is going to be in our users app template directory we needed to explicitly tell django.email_template_name
- The template used for generating the body of the email with the reset password link.subject_template_name
- The template used for generating the subject of the email with the reset password link.success_message
- The message that will be displayed upon a successful password reset request.success_url
- If not given any, django defaults to 'password_reset_done' after a successful password request. But I think it makes sense to just redirect the user to the home page without providing any additional template. from django.urls import path
from users.views import ResetPasswordView
urlpatterns = [
path('password-reset/', ResetPasswordView.as_view(), name='password_reset'),
]
{% extends "users/base.html" %}
{% block content %}
<div class="form-content my-3 p-3">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-5">
<div class="card shadow-lg border-0 rounded-lg mt-0 mb-3">
<div class="card-header justify-content-center">
<div id="error_div"></div>
<h3 class="font-weight-light my-4 text-center">Forgot Password?</h3>
</div>
{% if form.errors %}
<div class="alert alert-danger alert-dismissible" role="alert">
<div id="form_errors">
{% for key, value in form.errors.items %}
<strong>{{ value }}</strong>
{% endfor %}
</div>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
<div class="card-body">
<form method="POST">
{% csrf_token %}
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group">
<label class="small mb-1" for="id_email">Email</label>
<input type="email" name="email" class="form-control"
autocomplete="email" maxlength="254" required id="id_email"
placeholder="Enter email">
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group mt-0 mb-1">
<button type="submit" class="col-md-12 btn btn-dark">Submit
</button>
</div>
</div>
</div>
</form>
</div>
<div class="card-footer text-center">
<div class="small">
<a href="{% url 'users-register' %}">Create A New Account</a><br><br>
<a href="{% url 'login' %}">Back To Login</a><br>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
{% autoescape off %}
To initiate the password reset process for your {{ user.email }} Django Registration/Login App Account,
click the link below:
{{ protocol }}://{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
If clicking the link above doesn't work, please copy and paste the URL in a new browser
window instead.
Sincerely,
The Developer
{% endautoescape %}
Django - Registration/Login App Password Reset
<a href="{% url 'password_reset' %}"><i>Forgot Password?</i></a>
PasswordResetConfirmView
is the view responsible for presenting this password reset form, and validating the token i.e. whether or not the token has expired, or if it has been used already.PasswordResetConfirmView
to our main project's url patterns.from django.urls import path
from django.contrib.auth import views as auth_views
urlpatterns = [
path('password-reset-confirm/<uidb64>/<token>/',
auth_views.PasswordResetConfirmView.as_view(template_name='users/password_reset_confirm.html'),
name='password_reset_confirm'),
]
{% extends "users/base.html" %}
{% block title %} Password Reset {% endblock title%}
{% block content %}
<div class="form-content my-3 p-3">
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-5">
{% if validlink %}
<div class="card shadow-lg border-0 rounded-lg mt-0 mb-3">
<div class="card-header justify-content-center">
<h3 class="font-weight-light my-4 text-center">Reset Your Password</h3>
</div>
{% if form.errors %}
<div class="alert alert-danger alert-dismissible" role="alert">
<div id="form_errors">
{% for key, value in form.errors.items %}
<strong>{{ value }}</strong>
{% endfor %}
</div>
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
{% endif %}
<div class="card-body">
<form method="POST">
{% csrf_token %}
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group">
<label class="small mb-1" for="id_new_password1">New Password</label>
<input type="password" name="new_password1" autocomplete="new-password"
class="form-control" required id="id_new_password1"
placeholder="Enter password"/>
<span>
</span>
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group">
<label class="small mb-1" for="id_new_password2">New Password Confirmation</label>
<input type="password" name="new_password2" autocomplete="new-password"
required id="id_new_password2" class="form-control"
placeholder="Confirm password"/>
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-10 offset-md-1">
<div class="form-group mt-0 mb-1">
<button type="submit" class="col-md-12 btn btn-dark" id="reset">Reset Password</button>
</div>
</div>
</div>
</form>
</div>
</div>
{% else %}
<div class="alert alert-warning">
The password reset link was invalid, possibly because it has already been used.
Please request a new password reset.
</div>
{% endif %}
</div>
</div>
</div>
</div>
{% endblock content %}
PasswordResetCompleteView
will present a view letting the user know that his/her password is successfully changed.from django.urls import path
from django.contrib.auth import views as auth_views
urlpatterns = [
path('password-reset-complete/',
auth_views.PasswordResetCompleteView.as_view(template_name='users/password_reset_complete.html'),
name='password_reset_complete'),
]
{% extends "users/base.html" %}
{% block content %}
<div class="container my-3 p-3">
<div class="row justify-content-center">
<div class="col-lg-5">
<div class="card shadow-lg border-0 rounded-lg mt-0 mb-3">
<div class="alert alert-info">
Your password has been set. You may go ahead and <a href="{% url 'login' %}">Login Here</a>
</div>
</div>
</div>
</div>
</div>
{% endblock content %}
# email configs
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_USE_TLS = True
EMAIL_PORT = 587
EMAIL_HOST_USER = str(os.getenv('EMAIL_USER'))
EMAIL_HOST_PASSWORD = str(os.getenv('EMAIL_PASSWORD'))
EMAIL_BACKEND
is the SMTP backend that Email will be sent through.EMAIL_HOST
is the host to use for sending email.EMAIL_USE_TLS
- Whether to use a TLS (secure) connection when talking to the SMTP server. This is used for explicit TLS connections, generally on port 587.EMAIL_PORT
- Port to use for the SMTP server defined in EMAIL_HOST.EMAIL_HOST_USER
and EMAIL_HOST_PASSWORD
are username and password to use for the SMTP server respectively. To keep them safe, put them in .env file and retrieve them here as we have seen how to do in the last part of the series.python manage.py runserver
in your terminal.