Die Administrationsoberfläche ausbauen
Wir wollen die Event-Verwaltung noch ein bisschen ausbauen und ein paar Actions hinzufügen. Dafür öffnen wir die Datei event_manager/events/admin.py und erweitern die Klasse EventAdmin.
Admin Actions
Nun möchten wir auf der Events-Übersicht mehrere
Events markieren und alle auf einen Schlag inaktiv setzen können.
Bisher gibt es im Aktion-Dropdown nur eine Aktion: ausgewählte Events löschen.
Wollten wir aber ausgewählte Events nicht löschen, sondern nur auf aktiv bzw.
inaktiv stellen, müssen wir jedes Event anklicken und auf der Eventseite
die is_active-Eigenschaft ändern. Das ist mühselig, wenn man
das bei mehreren Events machen möchte. Dafür gibt es sogenannte Actions.
Wir fügen nun diese beiden Methoden hier in usere EventAdmin-Klasse ein:
@admin.register(Event)
class EventAdmin(admin.ModelAdmin):
# ... mehr Code
list_filter = ("category",)
list_display = "date", "author", "name", "category"
actions = ["make_active", "make_inactive"]
@admin.action(description="Setze Events active")
def make_active(self, request, queryset):
"""Set all Events to active."""
queryset.update(is_active=True)
@admin.action(description="Setze Events inactive")
def make_inactive(self, request, queryset):
"""Set all Events to inactive."""
queryset.update(is_active=False)
Der @admin.action-Decorator ist optional und macht nichts
weiter, als der Aktion in dem Aktionen-Dropdown-Feld einen greifbaren
Namen zu geben. Interessant sind jetzt die beiden Methoden
make_active bzw. make_inactive.
Diese beiden Methoden unserer EventAdmin-Klasse haben den
Parameter queryset. Dieses queryset entspricht den auswählten
also markierteren Events in der Eventübersicht. Führt man nun
eine Aktion aus, bekommt die jeweilige Methode diese Events als
queryset übergeben und wir können jetzt eine Aktion auf jeden dieser
Events ausführen.
make_active zum Beispiel setzt die is_active Eigenschaft auf
true und aktiviert damit die ausgewählten Events.
Mit Aktionen kann man also sehr einfach und schnell mehrere Objekte auf einmal ändern, löschen oder was auch immer man tun möchte. In unserem Fall haben wir die beiden Methoden so definiert, dass sie alle ausgewählten Events entweder auf aktiv oder inaktiv setzen.
@admin.action(description="Setze Events active")
def make_active(self, request, queryset):
"""Set all Events to active."""
queryset.update(is_active=True)
Damit diese beiden Methoden jetzt in der Admin auch registriert sind,
müssen wir die Methoden-Referenzen an die actions-Liste übergeben.
actions = ["make_active", "make_inactive"]
Mehr zu AdminActions gibt es in der Django-Doku:
https://docs.djangoproject.com/en/stable/ref/contrib/admin/actions/
Read Only Felder
Falls wir Felder in der Administrationsoberfläche readonly haben möchten,
d.h., dass sie zumindest über die Admin nicht mehr geändert werden können,
gibt es das Attribut readonly_fields. Wir wollen, dass der Autor eines
Events nachträglich nicht mehr geändert werden kann und fügen folgendes in die
Klasse ein:
readonly_fields = ("author",)
Damit sind alle Felder des Tuples auf readonly. Bei Tupeln mit nur einem Element muss das Komma am Ende stehen, damit Python das als Tuple erkennt.
Die fertige EventAdmin-Klasse sieht jetzt so aus:
@admin.register(Event)
class EventAdmin(admin.ModelAdmin):
list_display = (
"date",
"author",
"name",
"category",
)
list_display_links = ("name",)
list_filter = ("category",)
search_fields = ["name"]
actions = ["make_active", "make_inactive"]
readonly_fields = ("author",)
@admin.action(description="Setze Events active")
def make_active(self, request, queryset):
"""Set all Entries to active."""
queryset.update(active=True)
@admin.action(description="Setze Events inactive")
def make_inactive(self, request, queryset):
"""Set all Entries to inactive."""
queryset.update(active=False)
Fachmethoden in der Liste angeben
Bisher hatten wir in list_display nur gewöhnliche Felder angezeigt, zum
Beispiel Name oder Autor. Was ist aber, wenn wir zum Beispiel für das
Kategoriemodell in der Übersicht auch die Anzahl der Events anzeigen wollten?
Das Category - Model besitzt die methode num_of_events, welche wir im
Zusammenhang mit Formularen für das Model angelegt hatten. Diese Methode
liefert die Events einer Kategorie.
Wir erinnern uns:
class Category(DateMixin):
"""Eine Kategorie für einen Event."""
name = models.CharField(max_length=100, unique=True)
sub_title = models.CharField(max_length=200, null=True, blank=True)
description = models.TextField(null=True, blank=True)
class Meta:
ordering = ["name"]
def __str__(self):
return self.name
def num_of_events(self):
"""Die Anzahl der Events einer Kategorie."""
return self.events.count()
Wir können diese Methode in list_display im Admin-Model genauso angeben, wie jedes beliebige
andere Feld. Passen wir also die Klasse CategoryAdmin an:
@admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
list_display = "id", "name", "sub_title", "num_of_events"
list_display_links = ("name", "sub_title")
list_filter = ("events", "sub_title")
search_fields = ["name"]
Queryset überschreiben
Auf die Adminoberfläche haben alle User Zugriff, die den Staff-Status gesetzt
haben. Wir könnten zum Beispiel implementieren, dass Adminuser, d.h. User mit
dem Superuser-Status alle Events sehen können, alle anderen, zum Beispiel
Moderatoren, nur eigene Events. Dafür lässt sich die Methode get_queryset()
überschreiben.
def get_queryset(self, request):
"""Only superusers can see all events."""
qs = super().get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(author=request.user)
Die Django-Adminoberfläche bietet noch vieles mehr, was angepasst werden und verändert werden kann. Das soll nur ein kurzer Einblick sein, was man mit relativ wenig Aufwand anpassen kann.