Die Administrationsoberfläche ausbauen
Wir wollen die Event-Verwaltung noch ein bisschen ausbauen. Die erste Änderung soll eine kleine Schönheitskorrektur auf der Event-Detailseite sein. Aktuell kann man die Mingroups in einem Drop-Down-Feld auswählen. Wir wollen dies ändern und aus dem Drop-Down-Feld ein Reihe von Radio-Buttons machen, die vertikal angeordnet sind.
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. Der @admin.action
-Dekorator
setzt noch die Eigenschaft description
auf einen sprechenden Namen.
@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.
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",)
radio_fields = {
"category": admin.HORIZONTAL,
"min_group": admin.VERTICAL,
}
@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.
eine neue Djangoadmin Oberfläche
Wer eine schönere Djangoadmin-Oberfläche ohne viel Arbeit haben möchte, sollte sich mal Grapelli ansehen.
Damit lassen sich mit einfachen Mitteln deutliche Verbesserungen in der Optik erzielen.