Mettre un formulaire de connexion django sur chaque page

Je voudrais que le formulaire de connexion (AuthenticationForm from django.consortingb.auth) apparaisse sur chaque page de mon site si l’utilisateur n’est pas connecté. Lorsque l’utilisateur se connecte, il sera redirigé vers la même page. S’il y a une erreur, l’erreur sera affichée sur la même page avec le formulaire.

Je suppose que vous avez besoin d’un processeur de contexte pour fournir le formulaire à chaque modèle. Mais alors, vous auriez également besoin de toutes les vues pour traiter le formulaire publié? Est-ce que cela signifie que vous devez créer un middleware? Je suis un peu perdu.

Y a-t-il un moyen accepté de le faire?

Ok, j’ai finalement trouvé un moyen de le faire, même si je suis sûr qu’il y a de meilleurs moyens. J’ai créé une nouvelle classe de middleware appelée LoginFormMiddleware. Dans la méthode process_request, gérez le formulaire plus ou moins comme le fait la vue de connexion auth:

class LoginFormMiddleware(object): def process_request(self, request): # if the top login form has been posted if request.method == 'POST' and 'is_top_login_form' in request.POST: # validate the form form = AuthenticationForm(data=request.POST) if form.is_valid(): # log the user in from django.consortingb.auth import login login(request, form.get_user()) # if this is the logout page, then redirect to / # so we don't get logged out just after logging in if '/account/logout/' in request.get_full_path(): return HttpResponseRedirect('/') else: form = AuthenticationForm(request) # attach the form to the request so it can be accessed within the templates request.login_form = form 

Maintenant, si vous avez le processeur de contexte de demande installé, vous pouvez accéder au formulaire avec:

 {{ request.login_form }} 

Notez qu’un champ masqué ‘is_top_login_form’ a été ajouté au formulaire afin que je puisse le distinguer des autres formulaires publiés sur la page. De plus, l’action du formulaire est “.” au lieu de la vue de connexion d’authentification.

En utilisant django.consortingb.auth, vous pouvez placer le code du formulaire dans le modèle de base comme suit:

 
{% csrf_token %}

Il suffit de modifier la valeur suivante au lieu de:

  

Ce sera maintenant:

  

Pour accéder à l’object de requête, assurez-vous d’inclure

 'django.core.context_processors.request' 

dans vos processeurs de contexte de modèle. De cette façon, vous n’avez pas besoin d’écrire de processeurs de contexte pour les connexions car vous utilisez les vues intégrées de Django.

Le moyen le plus simple est probablement de mettre le formulaire manuellement dans un gabarit de base, comme ceci:

 {% if user.is_authenticated %} 
{% csrf_token %}
{% else %} {# display something else here... #} {% endif %}

puis écrivez simplement une vue associée à une URL nommée “login” pour gérer le formulaire comme vous le feriez normalement (en utilisant un object de formulaire correspondant au formulaire ci-dessus). Demandez à la vue de redirect vers request.META['HTTP_REFERER'] pour l’afficher sur la même page que celle qui a été soumise.

Cette approche évite le middleware ou le besoin de rendre un formulaire disponible pour chaque modèle dans le contexte.

Mise à jour : Cette approche présente certains problèmes. besoin d’y réfléchir un peu plus. J’espère que cela vous permettra au moins d’aller dans la bonne direction.

Sur la base de la réponse de asciitaxi, j’utilise ces classes de middleware pour me connecter et me déconnecter:

 class LoginFormMiddleware(object): def process_request(self, request): from django.consortingb.auth.forms import AuthenticationForm if request.method == 'POST' and request.POST.has_key('base-account') and request.POST['base-account'] == 'Login': form = AuthenticationForm(data=request.POST, prefix="login") if form.is_valid(): from django.consortingb.auth import login login(request, form.get_user()) request.method = 'GET' else: form = AuthenticationForm(request, prefix="login") request.login_form = form class LogoutFormMiddleware(object): def process_request(self, request): if request.method == 'POST' and request.POST.has_key('base-account') and request.POST['base-account'] == 'Logout': from django.consortingb.auth import logout logout(request) request.method = 'GET' 

An this in my template template:

 {% if not request.user.is_authenticated %} 
{% csrf_token %}

{{ request.login_form.non_field_errors }} {% for field in request.login_form %} {{ field.errors }} {{ field.label_tag}}: {{ field }} {% endfor %}

{% else %}
{% csrf_token %}

Logged in as {{ request.user.username }}.

{% endif %}

Remarques:

  • Les lignes request.method = ‘GET’ sont nécessaires pour les sites avec d’autres formulaires. Semble un peu mais akward, mais ça marche bien.
  • Comme ceci est affiché sur chaque page, je n’ai plus besoin du cas spécial de déconnexion, car je n’ai simplement pas besoin d’une page de déconnexion séparée
  • J’ai besoin d’une certaine distinction entre mon formulaire de connexion / déconnexion AVANT de vérifier s’il est valide (appelant donc la classe AuthenticationForm. Sinon, il y aura des erreurs quand il s’agira de pages avec plus de formulaires). les cas pertinents