Système d'authentification personnalisé django avec AbstractUser

Nous donnons ici un cours complet et progressif pour mettre en place un système d'authentification Django avec un modèle utilisateur personnalisé basé sur la classe AbstractUser, tout en fournissant une explication détaillé du contenu des composant : modèle, CustomUser, vues, URLs, settings.py ainsi que la structure et contenu des fichiers de templates. .etc

1. Pourquoi personnaliser la gestion des utilisateurs avec AbstractUser ?

Django fournit un modèle User par défaut. Lorsque vous avez besoin d’ajouter des champs (téléphone, photo, adresse…), hériter de AbstractUser est la solution la plus simple : vous conservez toutes les fonctionnalités (authentification, permissions, staff, superuser, etc.) tout en ajoutant vos propres champs. C’est exactement votre choix ici avec CustomUser.

2. Démarrage du projet 'django_custom_user' et de l’application principale

Enregistrement de l'application au niveau du fichier settings.py

Activez l’application dans INSTALLED_APPS et déclarez le modèle utilisateur personnalisé avant toute migration (voir §6).

3. Le modèle utilisateur CustomUser (héritage d’AbstractUser)

Dans accounts/models.py, nous faisant un héritage de la classe AbstractUser afin de pouvoir créer la classe CustomUser(AbstractUser) permettant de gérer les utilisateurs d'une façon personnalisée tout ajoutant les champs souhaités comme: phone_number, profile_picture...

Points clés :

  1. Les champs personnalisés: (phone_number, profile_picture, date_of_birth, address) complètent ceux d’AbstractUser.
  2. Le changement de related_name : pour groups et user_permissions évite des collisions avec le modèle parent, bonne pratique courante lorsqu’on réécrit ces relations.
  3. La méthode __str__ : privilégie l’email s’il existe (sinon le username).

 

Alert : Attention !
IMPORTANT : Déclarez AUTH_USER_MODEL = 'accounts.CustomUser' avant la première migration, sans quoi vous devrez repartir d’une base vide si vous changez d’avis plus tard. (Voir §6)

4. Les formulaires (création et mise à jour de profil)

Vous devez à ce moment là créer un fichier "accounts/forms.py" dont le but de personnaliser les champs du formulaire d'enregistrement des utilisateurs. Vous devez créer deux classes:

  1. CustomUserCreationForm : Classe qui hérite de la classe UserCreationForm pour l'enregistrement des utilisateur avec des champs personnalisés.
  2. ProfileUpdateForm : Classe qui hérite de la classe models.ModelForm pour la mise à jour des données de l'utilisateur

accounts/forms.py :

Ces formulaires correspondent aux vues SignUpView et ProfileUpdateView que vous devez définir au niveau du fichier "accounts/views.py"

5. Vues d’authentification et de profil

Afin de faciliter et automatiser les tâches, vous devez opter au vues génériques (generic view). Vous devez ainsi créer les classes : CustomLoginView, CustomLogoutView, SignUpView, ProfileView, ProfileUpdateView .etc

5.1 class CustomLoginView(LoginView)

  1. Héritage : Hérite de LoginView (vue générique Django pour la connexion)
  2. Fonction : Gère le processus d'authentification des utilisateurs
  3. Personnalisation :
    • template_name : Spécifie le template HTML personnalisé pour la page de login
    • form_valid() : Surchargée pour ajouter un message de bienvenue personnalisé après connexion réussie

5.2 class CustomLogoutView(LogoutView)

  1. Héritage : Hérite de LogoutView (vue générique Django pour la déconnexion)
  2. Fonction : Gère la déconnexion sécurisée des utilisateurs
  3. Personnalisation :
    • dispatch() : Surchargée pour afficher un message de confirmation seulement si l'utilisateur était authentifié

5.3 class SignUpView(CreateView)

  1. Héritage : Hérite de CreateView (vue générique pour la création d'objets)
  2. Fonction : Crée de nouveaux comptes utilisateurs
  3. Configuration :
    • form_class : Utilise un formulaire personnalisé CustomUserCreationForm
    • success_url : Redirige vers la page de login après inscription réussie
    • form_valid() : Ajoute un message de succès après création du compte

5.4 class ProfileView(LoginRequiredMixin, TemplateView)

  1. Héritage : Hérite de TemplateView + LoginRequiredMixin
  2. Fonction : Affiche le profil de l'utilisateur connecté
  3. Sécurité : LoginRequiredMixin empêche l'accès aux utilisateurs non authentifiés
  4. get_context_data() : Injecte les données de l'utilisateur dans le contexte du template

5.5 class ProfileUpdateView(LoginRequiredMixin, UpdateView)

  1. Héritage : Hérite de UpdateView + LoginRequiredMixin
  2. Fonction : Permet la modification du profil utilisateur
  3. Comportement :
    • get_object() : Retourne l'utilisateur connecté comme objet à modifier
    • form_class : Utilise ProfileUpdateForm pour limiter les champs modifiables
    • form_valid() : Message de confirmation après mise à jour réussie

5.6 Fonctionnalités avancées

  1. Système de messages : Feedback utilisateur via messages.success() et messages.info()
  2. Sécurité : Protection des vues avec LoginRequiredMixin
  3. URLs dynamiques : reverse_lazy() pour éviter les imports circulairesPersonnalisation : Adaptation des vues génériques de Django aux besoins spécifiques

Fichier "accounts/views.py"

6. Réglages settings.py (statique, médias, auth)

Mise à jour du fichier settings.py :

  1. STATICFILES_DIRS : permet de servir vos assets de développement (CSS/JS/images) depuis BASE_DIR/static.
  2. MEDIA_URL et MEDIA_ROOT : configurent l’upload utilisateur (ex. photos de profil).
  3. LOGIN_REDIRECT_URL et LOGOUT_REDIRECT_URL : Fixent les redirections après login/logout.
  4. AUTH_USER_MODEL : Demande à django d'utiliser un système d'authentification basé sur le modèle CustomUser. Cette commande doit être défini avant makemigrations/migrate.

7. Routage (URLs projet + app)

django_custom_user/accounts/urls.py

django_custom_user/urls.py

 

Remarque
L’ajout de static(settings.MEDIA_URL, ...) en mode DEBUG permet de servir les médias en développement (utile pour afficher la photo de profil).

8. Templates (structure et exemples minimaux)

Arborescence du répertoire templates:

Exemples très succincts (à adapter à votre charte):

templates/base.html

<!doctype html>
<html lang="fr">
  <head>
    <meta charset="utf-8" />
    <title>{% block title %}Site{% endblock %}</title>
    <link rel="stylesheet" href="{% static 'css/site.css' %}">
  </head>
  <body>
    {% if messages %}
      <ul class="messages">
        {% for m in messages %}<li class="{{ m.tags }}">{{ m }}</li>{% endfor %}
      </ul>
    {% endif %}

    <nav>
      {% if user.is_authenticated %}
        Bonjour {{ user.username }} |
        <a href="{% url 'profile' %}">Profil</a> |
        <a href="{% url 'logout' %}">Déconnexion</a>
      {% else %}
        <a href="{% url 'login' %}">Connexion</a> |
        <a href="{% url 'signup' %}">Inscription</a>
      {% endif %}
    </nav>

    <main>{% block content %}{% endblock %}</main>
  </body>
</html>

templates/index.html

{% extends "base.html" %}
{% block title %}Accueil{% endblock %}
{% block content %}
  <h1>Accueil</h1>
  <p>Bienvenue sur le site.</p>
{% endblock %}

templates/registration/login.html

{% extends "base.html" %}
{% block title %}Connexion{% endblock %}
{% block content %}
  <h2>Connexion</h2>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Se connecter</button>
  </form>
{% endblock %}

templates/registration/signup.html

{% extends "base.html" %}
{% block title %}Inscription{% endblock %}
{% block content %}
  <h2>Créer un compte</h2>
  <form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">S'inscrire</button>
  </form>
{% endblock %}

templates/registration/profile.html

{% extends "base.html" %}
{% block title %}Mon profil{% endblock %}
{% block content %}
  <h2>Profil</h2>
  <p><strong>Nom d'utilisateur :</strong> {{ user_profile.username }}</p>
  <p><strong>Email :</strong> {{ user_profile.email }}</p>
  <p><strong>Téléphone :</strong> {{ user_profile.phone_number }}</p>
  <p><strong>Date de naissance :</strong> {{ user_profile.date_of_birth }}</p>
  <p><strong>Adresse :</strong> {{ user_profile.address|linebreaksbr }}</p>
  {% if user_profile.profile_picture %}
    <img src="{{ user_profile.profile_picture.url }}" alt="Photo de profil" width="120">
  {% endif %}
  <p><a href="{% url 'profile_edit' %}">Modifier mon profil</a></p>
{% endblock %}

templates/registration/profile_edit.html

{% extends "base.html" %}
{% block title %}Modifier le profil{% endblock %}
{% block content %}
  <h2>Modifier mon profil</h2>
  <form method="post" enctype="multipart/form-data">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Enregistrer</button>
  </form>
{% endblock %}








 

Younes Derfoufi
CRMEF OUJDA

Leave a Reply

Your email address will not be published. Required fields are marked *