Programmez la vue pour que les utilisateurs se connectent
Parfait ! Nous avons maintenant un moyen de stocker différents utilisateurs dans notre base de données. Néanmoins, pour savoir qui sont ces utilisateurs, nous devons leur donner un moyen de se connecter au site.
Découvrons maintenant en vidéo comment construire une vue qui sera notre portail de connexion.
Étape 1 : Créez le LoginForm
(formulaire de connexion)
Tout d’abord, créez un fichier forms.py
qui contiendra le formulaire de connexion.
(ENV) ~/fotoblog (master)
→ touch authentication/forms.py
Dans ce fichier, créez le LoginForm
.
# authentication/forms.py
from django import forms
class LoginForm(forms.Form):
username = forms.CharField(max_length=63, label='Nom d’utilisateur')
password = forms.CharField(max_length=63, widget=forms.PasswordInput, label='Mot de passe')
Vous remarquerez aussi que nous paramétrons le champ Mot de passe (« password ») pour qu’il utilise le widget forms.PasswordInput
. Un widget détermine la façon dont vous affichez le champ. Comme vous l’avez peut-être deviné, le widget PasswordInput
cache automatiquement la saisie en utilisant un <input>
HTML avec l’attribut type="password"
.
Étape 2 : Créez la vue de la page de connexion
Maintenant que nous avons notre formulaire de connexion, il est temps de l’inclure dans une vue.
# authentication/views.py
from django.shortcuts import render
from . import forms
def login_page(request):
form = forms.LoginForm()
if request.method == 'POST':
form = forms.LoginForm(request.POST)
if form.is_valid():
pass
return render(request, 'authentication/login.html', context={'form': form})
Super ! Le LoginForm
est maintenant utilisé dans la vue. Néanmoins, comme vous pouvez le constater, nous ne gérons pas réellement les données POST
pour l’instant.
Django est fourni avec une série de méthodes qui peuvent aider les développeurs à gagner du temps. Vous pouvez utiliser les fonctions login
et authenticate
du module django.contrib.auth
pour l’authentification.
Voici comment les utiliser dans une vue.
from django.contrib.auth import login, authenticate # import des fonctions login et authenticate
def login_page(request):
form = forms.LoginForm()
message = ''
if request.method == 'POST':
form = forms.LoginForm(request.POST)
if form.is_valid():
user = authenticate(
username=form.cleaned_data['username'],
password=form.cleaned_data['password'],
)
if user is not None:
login(request, user)
message = f'Bonjour, {user.username}! Vous êtes connecté.'
else:
message = 'Identifiants invalides.'
return render(
request, 'authentication/login.html', context={'form': form, 'message': message})
Commençons par nous intéresser à la fonction authenticate
. Cette fonction prend deux arguments : le nom d’utilisateur et le mot de passe.
Si les identifiants sont corrects, elle retourne l’utilisateur correspondant aux identifiants. Sinon, elle retourne None.
La fonctionauthenticate
seule ne gère pas la connexion de l’utilisateur. Pour cela, utilisez la fonctionlogin
. Elle prend deux arguments : l’objetrequest
et l’objetuser
correspondant à l’utilisateur qui doit être connecté.
Et nous y voilà ! Vous avez maintenant une vue qui permet à un utilisateur de se connecter au site.
Étape 3 : Ajoutez un gabarit, ou template
Nous avons spécifié que nous utilisons le gabaritauthentication/login.html
dans la vue login_page
. Créons ce gabarit maintenant !
Premièrement, créez les répertoires qui contiendront les gabarits. Nous en ajouterons un à chacune de nos applications, puis un à la racine du projet.
(ENV) ~/fotoblog (master)
→ mkdir -p authentication/templates/authentication
(ENV) ~/fotoblog (master)
→ mkdir -p blog/templates/blog/
(ENV) ~/fotoblog (master)
→ mkdir templates
Ensuite, créez les gabarits : commencez par un gabarit de base qui sera utilisé pour l’ensemble du projet, puis celui de la page de connexion.
# templates/base.html
<html>
<head>
<title>FotoBlog</title>
</head>
<body>
<h1>FotoBlog</h1>
{% block content %}{% endblock content %}
</body>
</html>
# authentication/templates/authentication/login.html
{% extends 'base.html' %}
{% block content %}
<p>{{ message }}</p>
<form method="post">
{{ form.as_p }}
{% csrf_token %}
<button type="submit" >Se connecter</button>
</form>
{% endblock content %}
Si vous avez déjà eu l’occasion de créer une application Django en utilisant l’héritage de gabarit, vous reconnaissez probablement l’expression {% extends base.html %}
. Vu que nous allons utiliser notre gabarit de base dans différentes applications, nous l’avons placé dans le répertoire des gabarits du projet, et non dans une application.
Lorsque APP_DIRS
est réglé sur True
, Django trouve automatiquement le répertoire templates/
quand il est situé dans une application. Néanmoins, comme nous plaçons le gabarit de base à la racine du projet, nous devons le spécifier danssettings.py
pour que Django puisse trouver ce répertoire.
Pour ce faire, modifiez votre fichiersettings.py
comme ceci :
# fotoblog/settings.py
...
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
BASE_DIR.joinpath('templates'), # <--- ajoutez cette ligne
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
...
Ce code dit à Django qu’il y a des gabarits dans le répertoire templates/
à la racine du projet. Un chemin absolu, c’est-à-dire depuis le répertoire racine, est nécessaire. Utilisez la constante BASE_DIR
pour permettre cela.
Étape 4 : Ajoutez l’URL à urlpatterns
Le LoginForm
est construit et incorporé à la vuelogin_page
. Vous avez maintenant un gabarit que vous pouvez utiliser pour générer la page HTML.
Vous n’avez plus qu’à inclure le modèle, ou pattern, d’URL dansurls.py
.
from django.contrib import admin
from django.urls import path
import authentication.views
urlpatterns = [
path('admin/', admin.site.urls),
path('', authentication.views.login_page, name='login'),
]
Étape 5 : Affichez la page de connexion
Parfait ! Démarrons le serveur de développement pour voir la nouvelle page de connexion. Voici la procédure en vidéo :
On dirait que la page de connexion s’affiche comme prévu. Il est temps de la tester !
Testez la fonctionnalité de connexion et ajoutez la déconnexion
Plus tard, nous construirons une page d’inscription pour permettre aux utilisateurs de rejoindre le site. Mais pour l’instant, commençons par créer un utilisateur dans le shell Django et utilisons-le pour tester la fonctionnalité de connexion. Voici la technique en vidéo :
Pour ouvrir le shell Django, exécutez python manage.py shell
.
Étape 1 : Créez un utilisateur
Importez votre modèle User
personnalisé dans le shell Django.
>>> from authentication.models import User
>>> User.objects.create_user(username='toto', password='S3cret!', role='CREATOR')
<User: toto>
Étape 2 : Testez la fonctionnalité de connexion
Maintenant que nous avons un utilisateur stocké dans la base de données, retournons à la page de connexion et essayons de nous connecter.
Super, ça a marché ! Réessayons avec un mauvais mot de passe !
Parfait !
Étape 3 : Créez une vue de déconnexion
Maintenant que vous pouvez vous connecter, il serait logique que vous puissiez aussi vous déconnecter. Comment faire ? La réponse en vidéo :
Ajoutons une vue de déconnexion.
# authentication/views.py
from django.contrib.auth import authenticate, login, logout
from django.shortcuts import redirect, render
from . import forms
def logout_user(request):
logout(request)
return redirect('login')
def login_page(request):
...
Pour cela, vous allez utiliser une autre fonction — logout
— de django.contrib.auth
.
La vue dit à Django de déconnecter l’utilisateur. Vous utilisez ensuite la fonction redirect pour rediriger l’utilisateur vers la page de connexion. La fonction redirect
peut prendre un nom de vue, comme spécifié dans urls.py
.
Étape 4 : Ajouter la vue de déconnexion aux modèles d’URL
Et maintenant, ajoutons une nouvelle entrée aux modèles d’URL.
# fotoblog/urls.py
urlpatterns = [
...
path('logout/', authentication.views.logout_user, name='logout'),
]
Étape 5 : Ajoutez le gabarit de déconnexion
Pour finir, ajoutez un lien vers la page de déconnexion dans base.html
. Ainsi, il est visible dès qu’un utilisateur est connecté, du moment que vous étendez base.html
.
# templates/base.html
<html>
<head>
<title>FotoBlog</title>
</head>
<body>
<h1>FotoBlog</h1>
{% block content %}{% endblock content %}
{% if user.is_authenticated %}
<p>Vous êtes connecté en tant que {{ request.user }}. <a href="{% url 'logout' %}">Se déconnecter</a></p>
{% endif %}
</body>
</html>
Vous pouvez toujours accéder à l’objet user
dans le gabarit. Il correspond à l’utilisateur qui est en train de naviguer sur le site. Il est important de noter que Django représente un utilisateur anonyme avec un objet de type AnonymousUser.
Par conséquent, la seule présence d’un objet user
ne suffit pas à nous indiquer si l’utilisateur est authentifié.
Pour le vérifier, vous devez utiliser la méthode user.is_authenticated
. Elle renvoie True
si l’utilisateur est authentifié, ou False
dans le cas contraire.
Et maintenant, essayez les fonctionnalités de connexion et de déconnexion.
Restreignez l’accès à une partie du site aux utilisateurs connectés uniquement
Maintenant que vous pouvez connecter et déconnecter des utilisateurs, créons une page d’accueil vers laquelle rediriger les utilisateurs une fois connectés. Comme cette page ne s’occupe pas de l’authentification, vous allez la créer dans l’application blog
. La procédure en vidéo ci-dessous :
Étape 1 : Ajoutez la vue
Commençons par une vue :
# blog/views.py
def home(request):
return render(request, 'blog/home.html')
Étape 2 : Ajoutez un gabarit
Puis un gabarit :
# blog/templates/blog/home.html
{% extends 'base.html' %}
{% block content %}
<p>Vous êtes connecté !</p>
{% endblock content %}
Étape 3 : Ajoutez le modèle d’URL
Ajoutez un modèle d’URL dans urls.py :
# urls.py
import blog.views
urlpatterns = [
...
path('home/', blog.views.home, name='home'),
]
Étape 4 : Configurez une redirection après connexion
Vous devez maintenant dire à Django de rediriger vers cette page après une connexion réussie.
# views.py
def login_page(request):
form = forms.LoginForm()
message = ''
if request.method == 'POST':
form = forms.LoginForm(request.POST)
if form.is_valid():
user = authenticate(
username=form.cleaned_data['username'],
password=form.cleaned_data['password'],
)
if user is not None:
login(request, user)
return redirect('home')
message = 'Identifiants invalides.'
return render(request, 'authentication/login.html', context={'form': form, 'message': message})
Étape 5 : Testez la connexion
Voyons ce qu’il se passe lorsque nous nous connectons.
Capture d’écran d’une page après connexion
Joli, mais qu’est-ce qu’il se passerait si je me déconnectais et que j’essayais d’accéder à cette page directement par le biais de l’URL ?
Ça, ce n’est pas censé arriver !
Il vous faut un moyen de restreindre l’accès à des pages pour que seuls les utilisateurs connectés puissent y accéder. Heureusement, Django fournit le décorateur login_required
, qui remplit exactement ce rôle.
Étape 6 : Restreignez l’accès à la page d’accueil
Utilisons le décorateur login_required
sur la vue home
en ajoutant les lignes suivantes au fichier blog/views.html.
# blog/views.py
from django.contrib.auth.decorators import login_required
@login_required
def home(request):
return render(request, blog/home.html')
Pour que ça fonctionne, vous devez dire à Django vers quelle page rediriger si l’utilisateur n’est pas connecté. Faites-le en configurant LOGIN_URL
avec l’URL de la page de connexion ou, encore mieux, avec le nom du modèle d’URL de la page de connexion (login) dans settings.py
.
# fotoblog/settings.py
LOGIN_URL = 'login'
Essayez à nouveau d’accéder à la page d’accueil sans être connecté. Vous allez voir que vous êtes maintenant redirigé vers la page de connexion.
En résumé
Vous pouvez utiliser la fonction
authenticate
pour vérifier les identifiants d’un utilisateur, et la méthodelogin
pour le connecter. Utilisez la méthodelogout
pour le déconnecter.La méthode
user.is_authenticated
vérifie si l’utilisateur actuel est connecté.Vous pouvez utiliser le décorateur login_required sur une vue pour restreindre l’accès à certaines parties du site aux utilisateurs connectés uniquement.
Maintenant que nous avons construit un système de connexion qui utilise des vues basées sur des fonctions, voyons comment nous servir du pouvoir des vues basées sur des classes pour rendre les choses encore plus faciles.