Formation incluse

Mise en place de la fonctionnalité de changement de mot de passe

Kevin TIAKOUANG DJOU
Kevin TIAKOUANG DJOU
8 Numéro de téléphone 2024 · 27,88 min lecture
0
Django
Mise en place de la fonctionnalité de changement de mot de passe

Introduction


Cet article fait suite aux trois articles précédents consacrés à la mise en place d'une authentification complète avec Django. Précédemment, nous avons implémenté la fonctionnalité de mot de passe oublié, permettant d'envoyer un lien par e-mail pour créer un nouveau mot de passe en cas d'oubli. Aujourd'hui, nous allons réaliser la fonctionnalité de changement de mot de passe. Ce dernier article conclura notre série sur l'authentification avec Django.

1. Creation du formulaire et de la vue de changement de mot de passe


Dans le fichier forms.py, nous créons le formulaire qui servira au changement de mot de passe :


 class ChangePasswordForm(forms.Form):

    current_password = forms.CharField(

        label='Current Password',

        widget=forms.PasswordInput(

            attrs={'class': 'form-control', 'id': 'current_password', 'placeholder': 'Current Password'}

        ),

        required=True,

    )

    new_password = forms.CharField(

        label='New Password',

        widget=forms.PasswordInput(

            attrs={'class': 'form-control', 'id': 'new_password', 'placeholder': 'New Password'}

        ),

        required=True,

    )

    confirm_password = forms.CharField(

        label='Confirm Password',

        widget=forms.PasswordInput(

            attrs={'class': 'form-control', 'id': 'confirm_password', 'placeholder': 'Confirm Password'}

        ),

        required=True,

    )

 

    def __init__(self, user, *args, **kwargs):

        super().__init__(*args, **kwargs)

        self.user = user

 

    def clean_current_password(self):

        current_password = self.cleaned_data.get('current_password')

        if not self.user.check_password(current_password):

            raise forms.ValidationError("The current password is incorrect.")

        return current_password

 

    def clean(self):

        cleaned_data = super().clean()

        new_password = cleaned_data.get("new_password")

        confirm_password = cleaned_data.get("confirm_password")

 

        if new_password and confirm_password and new_password != confirm_password:

            self.add_error('confirm_password', "The new passwords do not match.")

 

        return cleaned_data

 

Une fois le formulaire créé, nous passons à la vue pour le changement de mot de passe dans le fichier views.py :

from django.contrib.auth.mixins import LoginRequiredMixin

from .forms import ChangePasswordForm

 

class ChangePasswordView(LoginRequiredMixin, View):

    def get(self, request):

        form = ChangePasswordForm(user=request.user)

        return render(self.request, template_name='registration/change_password.html', context={"form": form})

 

    def post(self, request):

        form = ChangePasswordForm(user=self.request.user, data=request.POST)

        if form.is_valid():

            new_password = form.cleaned_data['new_password']

            try:

                with transaction.atomic():

                    request.user.set_password(new_password)

                    request.user.save()

                    messages.success(request, "Your password has been changed successfully.",

                                     extra_tags="success")

                    return redirect("login")

            except Exception as e:

                messages.error(request, f"An error occurred: {str(e)}", extra_tags="danger")

        else:

            # Handle form errors (e.g., current password incorrect, passwords do not match)

            messages.error(request, "Please correct the errors below.", extra_tags="warning")

 

        return render(request, 'registration/change_password.html', context={"form": form})

 

 

 

2. Mise en place du template


Le template utilisé dans la vue est structuré comme suit :


 {% load custom_filters %}

<!DOCTYPE html>

<html lang="en">

<head>

    <meta charset="UTF-8">

    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <title>Change Password</title>

    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">

</head>

<body>

<div class="container mt-5">

    <h2 class="mb-3">Change Password</h2>

    <div class="row">

        {% if messages %}

            {% for message in messages %}

                <div class="container-fluid p-0">

                    <div class="alert alert-{{ message.tags }} alert-dismissible" role="alert">

                        {{ message|safe }}

                        <button type="button" class="close" data-dismiss="alert" aria-label="Close">

                            <span aria-hidden="true">&amp;times;</span>

                        </button>

                    </div>

                </div>

            {% endfor %}

        {% endif %}

    </div>

    <form class="form" method="post">

        {% csrf_token %}

        <div class="form-group mr-sm-3 mb-2">

            <label for="{{ form.current_password.id_for_label }}" class="sr-only">Current Password</label>

            {% if form.current_password.errors %}

                {{ form.current_password|add_css_classes:'form-control is-invalid' }}

                {% for error in form.current_password.errors %}

                    <div class="invalid-feedback">{{ error }}</div>

                {% endfor %}

            {% else %}

                {{ form.current_password|add_css_classes:'form-control' }}

            {% endif %}

        </div>

        <div class="form-group mr-sm-3 mb-2">

            <label for="{{ form.new_password.id_for_label }}" class="sr-only">New Password</label>

            {% if form.new_password.errors %}

                {{ form.new_password|add_css_classes:'form-control is-invalid' }}

                {% for error in form.new_password.errors %}

                    <div class="invalid-feedback">{{ error }}</div>

                {% endfor %}

            {% else %}

                {{ form.new_password|add_css_classes:'form-control' }}

            {% endif %}

        </div>

        <div class="form-group mr-sm-3 mb-2">

            <label for="{{ form.confirm_password.id_for_label }}" class="sr-only">Confirm Password</label>

            {% if form.confirm_password.errors %}

                {{ form.confirm_password|add_css_classes:'form-control is-invalid' }}

                {% for error in form.confirm_password.errors %}

                    <div class="invalid-feedback">{{ error }}</div>

                {% endfor %}

            {% else %}

                {{ form.confirm_password|add_css_classes:'form-control' }}

            {% endif %}

        </div>

        <button type="submit" class="btn btn-primary mb-2">Change Password</button>

    </form>

</div>

<script src="https://code.jquery.com/jquery-3.7.1.slim.min.js"

        integrity="sha256-kmHvs0B+OpCW5GVHUNjv9rOmY0IvSIRcf7zGUDTDQM8=" crossorigin="anonymous"></script>

<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>

</body>

</html>

 

3. Ajout des URLs


Importez la vue dans le fichier urls.py :

from .views import ChangePasswordView

 

urlpatterns = [

    path('change-password/', ChangePasswordView.as_view(), name='change-password'),

]

 

 

4. Illustration


Un lien de changement de mot de passe est ajouté sur la page de profil :

<a class="btn btn-warning mb-3" href="{% url 'users:change-password' %}">Change your password</a>

 

 

 

 

 

 

 

Conclusion


Avec ce dernier article, nous avons complété la série sur l'authentification avec Django. La mise en place de la fonctionnalité de changement de mot de passe assure une sécurité renforcée en permettant à l'utilisateur de modifier son mot de passe depuis son compte, après vérification de l'actuel. Ces articles sur l'authentification créent une base solide pour des applications web sécurisées et prêtes à l'emploi. N'hésitez pas à explorer le code pour adapter et étendre ces fonctionnalités dans vos projets Django.

0

Applaudissez pour montrer votre soutien

Kevin TIAKOUANG DJOU

Kevin TIAKOUANG DJOU

2 Suivez-nous · Rédacteur pour Django

Passionné de Django pour sa facilité à créer des applications web robustes, je serais ravi de mettre mes compétences en Python-Django au service to… Lire la suite