• Aucun résultat trouvé

Maintenant que nous avons assimilé les bases, il est temps de passer aux vues permettant à un utilisateur de se connecter, déconnecter, etc. Nous n'aborderons pas ici l'enregistrement de nouveaux utilisateurs. En effet, nous avons déjà montré la fonction à utiliser, et le reste est tout à fait classique : un formulaire, une vue pour récupérer et enregistrer les informations, un template…

La connexion

Nous avons désormais des utilisateurs, ils n'ont plus qu'à se connecter ! Pour ce faire, nous aurons besoin des éléments suivants :

Un formulaire pour récupérer le nom d'utilisateur et le mot de passe ; Un template pour afficher ce formulaire ;

Une vue pour récupérer les données, les vérifier, et connecter l'utilisateur.

Commençons par le formulaire. Il ne nous faut que deux choses : le nom d'utilisateur et le mot de passe. Autrement dit, le formulaire est très simple. Nous le plaçons dans blog/forms.py :

Code : Python

class ConnexionForm(forms.Form):

username = forms.CharField(label="Nom d'utilisateur", max_length=30)

password = forms.CharField(label="Mot de passe", widget=forms.PasswordInput)

Rien de compliqué, si ce n'est le widget utilisé : forms.PasswordInput permet d'avoir une boîte de saisie dont les caractères seront masqués, afin d'éviter que le mot de passe ne soit affiché en clair lors de sa saisie.

Passons au template :

Code : Jinja

<h1>Se connecter</h1>

{% if error %}

<p><strong>Utilisateur inexistant ou mauvais de mot de passe.</strong></p>

{% endif %}

{% if user.is_authenticated %}

Vous êtes connecté, {{ user.username }} !

{% else %}

<form method="post" action=".">

{% csrf_token %} {{ form.as_p }}

<input type="submit"/> </form>

{% endif %}

La nouveauté ici est la variable user, qui contient l'instance User de l'utilisateur s'il est connecté, ou une instance de la classe AnonymousUser. La classe AnonymousUser est utilisée pour indiquer que le visiteur n'est pas un utilisateur connecté. User et AnonymousUser partagent certaines méthodes comme is_authenticated, qui permet de définir si le visiteur est connecté ou non. Une instance User retournera toujours True, tandis qu'une instance AnonymousUser retournera toujours

False. La variable user dans les templates est ajoutée par un processeur de contexte inclus par défaut. Notez l'affichage du message d'erreur si la combinaison utilisateur/mot de passe est incorrecte.

1. Afficher le formulaire ;

2. Après la saisie par l'utilisateur, récupérer les données ;

3. Vérifier si les données entrées correspondent bien à un utilisateur ; 4. Si c'est le cas, le connecter et le rediriger vers une autre page ; 5. Sinon, afficher un message d'erreur.

Vous savez d'ores et déjà comment réaliser les étapes 1, 2 et 5. Reste à savoir comment vérifier si les données sont correctes, et si c'est le cas connecter l'utilisateur. Pour cela, Django fournit deux fonctions, authenticate et login, toutes deux situées dans le module django.contrib.auth. Voici comment elles fonctionnent :

authenticate(username=nom, password=mdp) : si la combinaison utilisateur/mot de passe est correcte, authenticate renvoie l'entrée du modèle User correspondante. Si ce n'est pas le cas, la fonction renvoie None. login(request, user) : permet de connecter l'utilisateur. La fonction prend l'objet HttpRequest passé à la vue par le framework, et l'instance de User de l'utilisateur à connecter.

Attention ! Avant d'utiliser login avec un utilisateur, vous devez avant tout avoir utilisé authenticate avec le nom d'utilisateur et le mot de passe correspondant, sans quoi login n'acceptera pas la connexion. Il s'agit d'une mesure de sécurité.

Désormais, nous avons tout ce qu'il nous faut pour coder notre vue. Voici notre exemple :

Code : Python

from django.contrib.auth import authenticate, login

def connexion(request): error = False

if request.method == "POST":

form = ConnexionForm(request.POST) if form.is_valid():

username = form.cleaned_data["username"] # Nous récupérons le nom d'utilisateur

password = form.cleaned_data["password"] # … et le mot de passe

user = authenticate(username=username,

password=password) #Nous vérifions si les données sont correctes if user: # Si l'objet renvoyé n'est pas None

login(request, user) # nous connectons l'utilisateur

else: #sinon une erreur sera affichée error = True

else:

form = ConnexionForm()

return render(request, 'connexion.html',locals())

Et finalement la directive de routage dans crepes_bretonnes/urls.py :

Code : Python

url(r'^connexion/$', 'blog.views.connexion', name='connexion'),

Vous pouvez désormais essayer de vous connecter depuis l'adresse /connexion/. Vous devrez soit créer un compte manuellement dans la console si cela n'a pas été fait auparavant grâce à la commande manage.py createsuperuser , soit renseigner le nom d'utilisateur et le mot de passe du compte super-utilisateur que vous avez créé lors de votre tout premier syncdb.

Si vous entrez une mauvaise combinaison, un message d'erreur sera affiché, sinon, vous serez connectés !

La déconnexion

Heureusement, la déconnexion est beaucoup plus simple que la connexion. En effet, il suffit d'appeler la fonction logout de django.contrib.auth. Il n'y a même pas besoin de vérifier si le visiteur est connecté ou non (mais libre à vous de le faire si vous souhaitez ajouter un message d'erreur si ce n'est pas le cas par exemple).

Code : Python

from django.contrib.auth import logout

from django.shortcuts import render

from django.core.urlresolvers import reverse

def deconnexion(request): logout(request) return redirect(reverse(connexion))

Avec comme routage :

Code : Python

url(r'^deconnexion/$', 'blog.views.deconnexion', name='deconnexion'),

C'est aussi simple que cela !

En général

Comme nos utilisateurs peuvent désormais se connecter et se déconnecter, il ne reste plus qu'à pouvoir interagir avec eux. Nous avons vu précédemment qu'un processeur de contexte se chargeait d'ajouter une variable reprenant l'instance User de

l'utilisateur dans les templates. Il en va de même pour les vues.

En effet, l'objet HttpRequest passé à la vue contient également un attribut user qui renvoie l'objet utilisateur du visiteur. Celui-ci peut, encore une fois, être une instance User s'il est connecté, ou AnonymousUser si ce n'est pas le cas. Exemple dans une vue :

Code : Python

from django.http import HttpResponse

def dire_bonjour(request): if request.user.is_authenticated(): return HttpResponse("Salut, {0}

!".format(request.user.username)) return HttpResponse("Salut, anonyme.")

Maintenant, imaginons que nous souhaitions autoriser l'accès de certaines vues uniquement aux utilisateurs connectés. Nous pourrions vérifier si l'utilisateur est connecté, et si ce n'est pas le cas le rediriger vers une autre page, mais cela serait lourd et redondant. Pour éviter de se répéter, Django fournit un petit décorateur très pratique qui nous permet de nous assurer qu'uniquement des visiteurs authentifiés accèdent à la vue. Son nom est login_required et il se situe dans django.contrib.auth.decorators. En voici un exemple d'utilisation :

Code : Python

from django.contrib.auth.decorators import login_required

@login_required def ma_vue(request): …

Si l'utilisateur n'est pas connecté, il sera redirigé vers l'URL de la vue de connexion. Cette URL est normalement définie depuis la variable LOGIN_URL dans votre settings.py. Si ce n'est pas fait, la valeur par défaut est '/accounts/login/'. Comme nous avons utilisé l'URL '/connexion/' tout à l'heure, réindiquons-la ici :

Code : Python - Extrait de settings.py

LOGIN_URL = '/connexion/'

Il faut savoir que si l'utilisateur n'est pas connecté, non seulement il sera redirigé vers '/connexion/', mais l'URL complète de la redirection sera "/connexion/?next=/bonjour/". En effet, Django ajoute un paramètre GET appelé next qui contient l'URL d'où provient la redirection. Si vous le souhaitez, vous pouvez récupérer ce paramètre dans la vue gérant la connexion, et ensuite rediriger l'utilisateur vers l'URL fournie. Néanmoins, ce n'est pas obligatoire.

Sachez que vous pouvez également préciser le nom de ce paramètre (au lieu de next par défaut), via l'argument redirect_field_name du décorateur :

Code : Python

from django.contrib.auth.decorators import login_required

@login_required(redirect_field_name='rediriger_vers')

def ma_vue(request): …

Vous pouvez également spécifier une autre URL de redirection pour la connexion (au lieu de prendre LOGIN_URL dans le settings.py) :

Code : Python

from django.contrib.auth.decorators import login_required

@login_required(login_url='/utilisateurs/connexion/')

def my_view(request): …

Les vues génériques

L'application django.contrib.auth contient certaines vues génériques très puissantes et pratiques qui permettent de réaliser les tâches communes d'un système utilisateurs sans devoir écrire une seule vue : se connecter, se déconnecter, changer le mot de passe et récupérer un mot de passe perdu.

Pourquoi alors nous avoir expliqué comment gérer manuellement la (dé)connexion ?

Les vues génériques répondent à un besoin basique. Si vous avez besoin d'implémenter des spécificités lors de la connexion, il est important de savoir comment procéder manuellement.

Vous avez vu comment utiliser les vues génériques dans le chapitre dédié ; nous ne ferons donc ici que les lister, avec leurs paramètres et modes de fonctionnement.

Se connecter

Vue : django.contrib.auth.views.login. Arguments optionnels :

template_name : le nom du template à utiliser (par défaut registration/login.html). Contexte du template :

form : le formulaire à afficher ;

next : l'URL vers laquelle l'utilisateur sera redirigé après la connexion.

Affiche le formulaire et se charge de vérifier si les données saisies correspondent à un utilisateur. Si c'est le cas, la vue redirige l'utilisateur vers l'URL indiquée dans settings.LOGIN_REDIRECT_URL ou vers l'URL passée par le paramètre GET next s'il y en a un, sinon il affiche le formulaire. Le template doit pouvoir afficher le formulaire et un bouton pour l'envoyer.