User Login und Logout

Wir wollen den generierten Usern jetzt ermöglich, sich auf der Website einzuloggen. Ein vollständiger Authentifikationsprozess beinhaltet natürlich noch euch eine Registrierung.

Django auth

Django installiert die Authentifizierungs-App automatisch, wenn ein neues Projekt erstellt wird. In der Datei event_manager/settings/base.py unter den INSTALLED_APPS sehen wir, dass django.contrib.auth eine von mehreren integrierten Apps ist, die Django für uns installiert hat. Die Auth-Applikation bietet Views und URLs für die wichtigsten Authentifizierungs-Aufgaben wie login, logout oder Passwort ändern. Nur die Templates dazu müssen wir selber anlegen.

INSTALLED_APPS = [
    'user',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

Um die Auth-App zu nutzen, müssen wir diese auf Projektebene verlinken, dh. zu den event_manager/event_manager/urls.py hinzufügen.

path('accounts/', include('django.contrib.auth.urls')),
from django.conf import settings
from django.contrib import admin
from django.urls import include, path
from django.views.generic.base import RedirectView

urlpatterns = [
    path("", RedirectView.as_view(url="events")),
    path("admin/doc/", include("django.contrib.admindocs.urls")),
    path("i18n/", include("django.conf.urls.i18n")),
    path("admin/", admin.site.urls),
    path("events/", include("events.urls", namespace="events")),
    path('accounts/', include('django.contrib.auth.urls')),
]

if settings.DEBUG:
    import debug_toolbar

    urlpatterns = [
        path("__debug__/", include(debug_toolbar.urls)),
    ] + urlpatterns

Die jetzt eingebundene Authentifizierungs-App bietet uns mehrere Authentifizierungsansichten und URLs für die Anmeldung, Abmeldung und Passwortverwaltung.

Die Standar-Urls der Auth-App

Out of the box bietet uns die Auth-App folgende URLs für die wichtigsten Aktionen:

  • accounts/login/ [name=‘login‘]

  • accounts/logout/ [name=‘logout‘]

  • accounts/password_change/ [name=‘password_change‘]

  • accounts/password_change/done/ [name=‘password_change_done‘]

  • accounts/password_reset/ [name=‘password_reset‘]

  • accounts/password_reset/done/ [name=‘password_reset_done‘]

  • accounts/reset/<uidb64>/<token>/ [name=‘password_reset_confirm‘]

  • accounts/reset/done/ [name=‘password_reset_complete‘]

Die URLs sollten selbsterklärend sein. Bei Eingabe der URL accounts/login landet man folglicherweise auf einer Login-Maske, um sich am System anzumelden. Allerdings benötigen wir noch Templates und das Einrichten der URLs, um diese Aktionen zu ermöglichen.

Urls anpassen

Der Default-Urlpfad für die Login-App ist accounts. Falls man damit zufrieden ist, braucht man nichts weiter zu tun. Möchte man aber eine andere URL für den Login nutzen, zum Beispiel http://127.0.0.1:8000/user/login, dann muss man diesen Pfad in den Settings festlegen:

LOGIN_URL = "/user/login"

sowie in den event_manager/event_manager/urls.py die URLs zur Auth-App anpassen:

path("user/", include("django.contrib.auth.urls")),

Django sorgt dann selbständig dafür, dass bei dem Versuch, eine Aktion auszuführen, die eine Anmeldung benötigt, an die entsprechene URL weitergeleitet wird. Standardmäßig ist das wie gesagt accounts/login.

Views

Für die Standard-Aufgaben login, logout und password_change benötigen wir keine weiteren Views, diese werden von Django selber gestellt.

Templates für die Login Page

Wir müssen jetzt die Templates für die Views erstellen. Dazu legen wir in den Projekt-Templates unter user/templates/ ein neues Verzeichnis namens registration an. Django erwartet den Pfad registration innerhalb eines der Templates-Suchpfade, die wir in den Settings angelegt haben. Das beinhaltet auch die App user.

So sieht das User-Verzeichnis aktuell aus:

└── user
    ├── admin.py
    ├── apps.py
    ├── factories.py
    ├── forms.py
    ├── __init__.py
    ├── management
    │   └── commands
    ├── migrations
    ├── models.py
    ├── templates
    │   └── registration
    ├── urls.py
    └── views.py

Nun legen wird dort das Template für die Login-Seite an: event_manager/user/templates/registration/login.html

{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}

{% block content %}

<main class="form-signin">
  <form method="post">
    <img class="mb-4" src="{% static 'penglogo.png' %}" alt="" >
    <h1 class="h3 mb-3 fw-normal">Bitte einloggen</h1>

      {% csrf_token %}
      {{ form|crispy }}

    <div class="checkbox mb-3">
      <label>
        <input type="checkbox" value="remember-me"> Erinnere Dich
      </label>
    </div>
    <button class="w-100 btn btn-lg btn-primary" type="submit">Sign in</button>
    <p class="mt-5 mb-3 text-muted">&copy; 2019–2022</p>
  </form>
</main>
{% endblock %}

in den Settings müssen wir jetzt noch spezifizieren, wohin nach erfolgreichem Einloggen bzw. Ausloggen weitergeleitet wird. Per default werden wir auf das UserProfil weitergeleitet, was aber noch gar nicht implementiert ist. Wir wollen aber nach Login auf die Hauptseite umgeleitet werden. in den event_manager/settings/base.py legen wir diese Konstante an.

LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/'

Verlinkungen in der Base-Datei anpassen

Bisher konnten wir die Verlinkungen in der Top-Navigation nicht nutzen, zum Beispiel den Logout und Login. Das wollen wir jetzt nachholen und verändern die event_manager/templates/base.html. Wir müssen nur die Auskommentierten Zeilen wieder einkommentieren

<li>
    <a class="dropdown-item" href="{% url 'password_change' %}">Passwort ändern</a>
</li>

<li>
    <a class="dropdown-item" href="{% url 'logout' %}">Sign out</a>
</li>

Passwort ändern

Wir wollen noch eine Passwort ändern Seite hinzufügen: Im Verzeichnis event_manager/user/templates/registration legen wir zwei Dateien an: password_change_form.html und password_change_done.html

Das password_change_done-Formular sieht so aus:

{% extends 'base.html' %}

{% block head%}
Passwort erfolgreich geändert!
{% endblock %}

{% block content %}

Gratulation! Das Passwort wurde erfolgreich geändert!
<a href="{% url 'events:events' %}">Zur Übersichtsseite</a>
{% endblock %}

Das password_change_form-Formular sieht so aus:

{% extends 'base.html' %}
{% load crispy_forms_tags %}

{% block head%}
Log in
{% endblock %}

{% block content %}
<form method="post">
  {% csrf_token %}
{{ form|crispy }}
<button type="submit" class="btn btn-primary">Passwort ändern</button>
</form>
{% endblock %}

Wenn wir jetzt im eingeloggten Zustand die URL http://127.0.0.1:8000/accounts/password_change besuchen, sehen wir das Passwort-Ändern-Formular.

Eingeloggt das Login-Formular aufrufen

Einen kleinen Schönheitsfehler hat unser Login aber noch: wir können auch im eingeloggten Zustand die http://127.0.0.1:8000/accounts/login/ aufrufen. Besser wäre es, wenn das Login-Formular nur dann aufrufbar wäre, wenn wir nicht eingeloggt sind. Es müsste also sowas wie eine Weiterleitung geben.

Um dieses Problem kümmern wir uns im Kapitel „Registrierung“.