.. _user_model: .. index:: single: User single: auth single: get_user_model single: AUTH_USER_MODEL Das User-Model anpassen ************************** Für unsere App wird es nötig sein, dass wir Events Autoren zuordnen können, die diese eingestellt haben. User müssen sich also auf unserer Website registrieren und einloggen können, um Events zu erstellen. Django bietet out-of-the-box Zugriff auf das Default-User-Model. .. admonition:: Moment mal. Was ist denn eigentlich ein User-Model? Das User-Model ist auch ein Django-Model, welches bestimmte Felder besitzt, zum Beispiel das Feld ``username`` oder ``password``. Auch für dieses Model exisitiert eine Datenbank-Tabelle mit genau diesen Feldern, wie wir später sehen werden. Dieses Modell bietet zusätzlich Features wie Authentifizierung, Passwort-Hashing usw. Es wäre kein Problem, das User-Model aus ``django.contrib.auth.models`` zu importieren und damit unserem Event-Model einen Autor zu geben: Die Event-Autor Beziehung wäre wieder eine 1:N-Beziehung und wird wie schon bei der Category über ein ``ForeignKey``-Feld gelöst. Beispiel-Code, wie man es machen könnte, aber nicht machen sollte: .. code-block:: python from django.db import models from django.contrib.auth.models import User class Event(DateMixin): # überflüssiger Code wurde hier weggelassen author = models.ForeignKey( User, on_delete=models.CASCADE, related_name="events" ) Das Problem an dieser Stelle ist, dass wir hier auf das ``Default-User-Model`` referenzieren. Oft ist es allerdings so, dass wir in einem Django-Projekt auch das ``User-Model`` anpassen wollen. Oder die App in einer Umgebung eingesetzt werden soll, wo nicht das ``Default-User-Model`` genutzt wird. **Warum sollte man das User-Model ändern wollen?** Das Default-User-Model bietet eine Handvoll an nützlichen und notwendigen Attributen wie ``first_name``, ``staff_status``. Es könnte aber sein, dass man dem User-Model noch ein weiteres Feld hinzufügen möchte, zum Beispiel ``address`` oder ähnliches. Um dies zu realisieren, müssen wir **projektweit** ein modifiziertes User-Model ermöglichen. Auch wenn dieser Schritt anfangs gar nicht geplant ist, macht es Sinn, sich die Möglichkeit zumindest offen zu lassen. If you’re starting a new project, it’s highly recommended to set up a custom user model, even if the default User model is sufficient for you. --Django Dokumentation, Extending the existing User model .. admonition:: Best Practice In jedem neuen Projekt sollte das Anlegen eines eigenen User-Models einer der ersten Schritte sein. Dies muss allerdings noch vor der ersten Migration geschehen. Sonst könnte es passieren, dass innerhalb eines Projekts auf verschiedene User-Models verwiesen wird. ``_ Das angepasst User-Model ------------------------ Um ein eigenes User-Model zu implementieren, erstellen wir eine App mit dem angepassten User-Model, auf das wir dann projektweit Zugriff haben. Zusätzlich wird dieses User-Model im System registriert und auch vom System, dh. von Django selbst, genutzt. .. note:: Wichtig: Das muss **VOR der allerersten Migration** geschehen! Andernfalls referenzieren dann manche Tabellen noch auf das alte User-Model, was langfristig natürlich zu Problemen führen kann. eine user-App erstellen: =========================== Wir erstellen eine neue App namens ``user``. .. code-block:: shell (eventenv) python manage.py startapp user models-Datei anpassen: =========================== Wir modifizieren die Datei ``event_manager/user/models.py`` wie folgt: .. code-block:: python from django.contrib.auth.models import AbstractUser class User(AbstractUser): """Das ist das neue User-Model. Es hat bisher keine zusätzlichen Attribute.""" ... .. admonition:: Abstract User VS. AbstractBaseUser Django bietet zwei Klassen an, von dem unser ``User`` erben kann, die ``AbstractUser``- sowie die ``AbstractBaseUser``-Klasse. Wer die volle Kontrolle über das Benutzermodell benötigen, nimmt besser die ``AbstractBaseUser``-Klasse, muss sich dann aber auch darauf gefasst machen, viele Details selber nachzuimplementieren. Wer nur ein paar Dinge zum vorhandenen Benutzer hinzufügen möchten, z. B. ein zusätzliches Feld ``Role``, ein Adress-oder Sloganfeld, der verwendet besser die ``AbstractUser``-Klasse. In den meisten Fällen reicht die auch aus. Wir werden in diesem Buch ohnehin keine zusätzlichen Felder implementieren. Mehr zu diesem Thema hier: ``_ App in den Settings registrieren =================================== Damit die App von Django später auch gefunden wird, müssen wir sie in den Settings registrieren. Dazu öffnen wir die Datei ``event_manager/event_manager/settings.py`` und modifizieren folgende Zeilen: .. code-block:: python INSTALLED_APPS = [ "user", # <= das hier hinzufügen 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', "events", ] Wir müssen darauf achten, user ganz oben in den INSTALLED_APPS zu platzieren, damit später unsere Templates für die Registrierung und das Change-Password-Formular gefunden werden. Mehr dazu aber später. Nun müssen wir Django noch sagen, dass wir ein eigenes User-Model nutzen wollen. Dazu setzen wir ebenfalls in der Datei ``event_manager/event_manager/settings.py`` die ``AUTH_USER_MODEL``-Konstante auf das User-Model unserer neuen ``User``-App: .. code-block:: python AUTH_USER_MODEL = 'user.User' So sieht unsere Datei :file:`event_manager/user/models.py` nun aus: .. rli:: https://raw.githubusercontent.com/realcaptainsolaris/event_manager_code/main/models/events/1_user_model.py :language: python App in der Admin =================================== Tragen wir in die Datei ``event_manager/user/admin.py`` noch folgendes ein: .. code-block:: python from django.contrib import admin from django.contrib.auth.admin import UserAdmin from .models import User admin.site.register(User, UserAdmin) Die ``admin.py`` steuert das Aussehen des Models in der Administrationsoberfläche. Dazu aber später mehr. Zugriff auf das User-Model =================================== Wo auch immer wir das User-Model benötigen, sollten wir nicht direkt drauf zugreifen, sondern über die Helfermethode ``get_user_model``. So bleiben wir flexibel, wenn wir das User-Model ändern wollen. ``get_user_model`` gibt uns nämlich immer genau das User-Model zurück, welches wir in den Settings per ``AUTH_USER_MODEL`` referenzieren. Praktisch auch, wenn wir die App in einem anderen Projekt einbauen, und nicht wissen, welches User-Model genutzt wird. Einbinden des aktuellen User-Models in einem Beispielcode: .. code-block:: python from django.contrib.auth import get_user_model User = get_user_model() Wir haben nun alle nötigen Models erstellt und können diese nun migrieren. Wie das geht, erfahrt ihr im nächsten Kapitel. Später werden wir das ``User-Model`` auch nutzen, indem ein Event einem ``Autor`` zugeordnet werden kann. Weiterführende Informationen zum User-Model finden sich in der Django-Doku -------------------------------------------------------------------------- ``_