.. _admin_app:
.. index::
single: admin
single: Administrationsoberfläche
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.
Choice-Felder als Radio Buttons in der Admin darstellen
======================================================================
Wir öffnen die Datei ``event_manager/events/admin.py``
und modifizieren das ``EventAdmin``-Klasse:
.. code-block:: python
@admin.register(Event)
class EventAdmin(admin.ModelAdmin):
# anderer Code
radio_fields = {
"min_group": admin.VERTICAL,
}
Die Eigenschaft ``radio_fields`` der ModelAdmin-Klasse ermöglicht
uns komfortabel das Ändern der Eigenschaft:
.. image:: /images/admin_5_min_group.png
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``.
.. image:: /images/admin_6_actions.png
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:
.. code-block:: python
@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.
.. code-block:: python
@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.
.. code-block:: python
actions = ["make_active", "make_inactive"]
Mehr zu AdminActions gibt es in der Django-Doku:
``_
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:
.. code-block:: python
readonly_fields = ("author",)
Damit sind alle Felder des Tuples auf readonly.
Die fertige ``EventAdmin``-Klasse sieht jetzt so aus:
.. code-block:: python
@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:
.. code-block:: python
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:
.. code-block:: python
@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"]
.. image:: /images/category_admin_events.png
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.
.. code-block:: python
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.