Im letzten Beitrag haben wir uns angeschaut, warum die klassenbasierten Views (CBV) von Django notwendig sind und welche Vorteile sie im Vergleich zu funktionalen Views (FBV) bieten. In diesem Beitrag werden wir uns ausführlich mit der grundlegenden View-Klasse von Django befassen, die das Fundament aller CBVs darstellt.

„Um CBVs richtig zu verstehen, ist es wichtig, zu erfassen, wie django.views.View funktioniert und welche Struktur sie hat.“


1. Was ist die Django View-Klasse?

Alle klassenbasierten Views von Django verwenden die django.views.View-Klasse, von der sie erben.

from django.views import View

class MyView(View):
    def get(self, request, *args, **kwargs):
        # Logik zum Verarbeiten von GET-Anfragen
        ...

    def post(self, request, *args, **kwargs):
        # Logik zum Verarbeiten von POST-Anfragen
        ...

Merkmale der View-Klasse

  1. Trennung der Methoden nach HTTP-Methoden
    Wenn eine Anfrage eingeht, ruft Django intern automatisch die entsprechenden Funktionen wie get(), post(), put() und delete() durch die dispatch()-Methode auf.

    • Dadurch wird der Code übersichtlich, da keine Bedingungen wie „if request.method == 'GET': … else: …“ erforderlich sind, wie es bei FBVs der Fall ist.
  2. Vererbung und Erweiterbarkeit
    Durch die Vererbung von der View-Klasse können mehrere Kind-Views erstellt werden, wobei gemeinsame Logik im Elternklasse und individuelle Logik in den Kindklassen untergebracht werden kann, um die Wiederverwendbarkeit des Codes zu maximieren.


2. Grundstruktur und Prinzip der View-Klasse

Django View Struktur im LEGO-Stil

Das einfachste Beispiel

# views.py
from django.http import HttpResponse
from django.views import View

class HelloCBV(View):
    def get(self, request, *args, **kwargs):
        return HttpResponse("Hallo, CBV!")
  • get()-Methode: Wird ausgeführt, wenn eine GET-Anfrage (Adresse in die URL-Leiste eingeben, Link klicken usw.) gesendet wird.

  • HttpResponse("Hallo, CBV!"): Erstellt und gibt eine textbasierte Antwort zurück.

urls.py verbinden

# urls.py
from django.urls import path
from .views import HelloCBV

urlpatterns = [
    path('hello/', HelloCBV.as_view(), name='hello_cbv'),
]
  • Die .as_view()-Methode wandelt die CBV in eine Form um, die Django verstehen kann.

  • Wenn das URL-Muster verbunden ist, wird die get()-Methode von HelloCBV aufgerufen, wenn eine GET-Anfrage an http://example.com/hello/ gesendet wird.


3. Verwendung der View-Klasse und praktische Beispiele

In einem einfachen Fall wie oben wird es selten vorkommen, nur einen „string zurückzugeben“. In realen Projekten erfolgt häufig eine JSON-Antwort, Template-Rendering oder Datenbankabfragen. Wir werden hier JSON-Antworten und Template-Rendering als Beispiele betrachten.

3.1 Beispiel für die Verarbeitung von JSON-Antworten

# views.py
from django.http import JsonResponse
from django.views import View

class UserDataView(View):
    def get(self, request, *args, **kwargs):
        # Beispiel: Angenommen, wir erhalten die user_id als GET-Parameter
        user_id = request.GET.get('user_id', None)
        if not user_id:
            return JsonResponse({'error': 'Keine user_id angegeben'}, status=400)

        # Tatsächlich würden DB-Abfragen durchgeführt
        user_data = {
            'id': user_id,
            'name': f'User_{user_id}',
            'role': 'admin'
        }
        return JsonResponse(user_data, status=200)

    def post(self, request, *args, **kwargs):
        # JSON oder form-daten können im POST-Anfragekörper geparst werden.
        # request.POST, request.body, request.FILES usw. sind nutzbar.
        # In realen Anwendungen werden die JSON-Daten geparst und in der DB gespeichert.
        new_user_data = {
            'id': 123,
            'name': 'NewUser',
            'role': 'member'
        }
        return JsonResponse(new_user_data, status=201)
  • JsonResponse: Ein praktisches Werkzeug von Django zur einfachen Erstellung von JSON-Antworten.

  • request.GET, request.POST: Hiermit können GET/POST-Parameter vom HttpRequest-Objekt von Django abgerufen werden.

  • In der Praxis werden Daten meist in Verbindung mit DB-Modellen oder Serializer strukturiert verarbeitet.

3.2 Beispiel für Template-Rendering

# views.py
from django.shortcuts import render
from django.views import View

class GreetingView(View):
    def get(self, request, *args, **kwargs):
        context = {
            'title': 'Willkommen auf meiner Seite',
            'greeting': 'Hallo, dies ist eine GreetingView!'
        }
        return render(request, 'greeting.html', context)
<!-- templates/greeting.html -->
<!DOCTYPE html>
<html>
<head>
  <title>{{ title }}</title>
</head>
<body>
  <h1>{{ greeting }}</h1>
</body>
</html>
  • Die render()-Funktion sucht die Template-Datei (greeting.html) und gibt das gerenderte HTML als HttpResponse zurück.

  • Mit CBVs kann man im Inneren der Klasse einfach Templates rendern.


4. Erweiterbarkeit und Wiederverwendbarkeit der View-Klasse

Einer der größten Vorteile der View-Klasse ist die „Code-Wiederverwendbarkeit“. Je größer das Projekt wird, desto effizienter ist es, gemeinsame benötigte Logik (z. B. Logging, Authentifizierungsprüfungen, gemeinsame Datenbearbeitung) in der Elternklasse zu haben und von den Kindklassen zu erben.

4.1 Gemeinsame Logik in der Elternklasse

# views.py
from django.http import JsonResponse
from django.views import View

class BaseLoggingView(View):
    def dispatch(self, request, *args, **kwargs):
        # Gemeinsame Logik für alle Anfragen (GET/POST usw.) ausführen
        print(f"[Log] {request.method} Anfrage bei {request.path}")
        return super().dispatch(request, *args, **kwargs)

class ChildLoggingView(BaseLoggingView):
    def get(self, request, *args, **kwargs):
        data = {'message': 'GET-Antwort vom Kind'}
        return JsonResponse(data)

    def post(self, request, *args, **kwargs):
        data = {'message': 'POST-Antwort vom Kind'}
        return JsonResponse(data)
  • dispatch()-Methode: Eine Schlüssel-Methode, die es ermöglicht, die Ausführung von View-Logik vor und nach dem Aufruf zu steuern.

  • In diesem Beispiel wird für jede Anfrage ein Log erstellt, bevor super().dispatch() aufgerufen wird, um tatsächlich get(), post() usw. auszuführen.

4.2 Hinzufügen von Funktionen durch Mixin

Django verwendet häufig die Mixin-Technik, um „bestimmte Funktionen zu kombinieren“. Zum Beispiel kann man LoginRequiredMixin (Überprüfung, ob der Benutzer eingeloggt ist), PermissionRequiredMixin (Überprüfung der Berechtigung) in CBVs einfügen.

from django.contrib.auth.mixins import LoginRequiredMixin
from django.views import View
from django.http import JsonResponse

class SecuredView(LoginRequiredMixin, View):
    def get(self, request, *args, **kwargs):
        return JsonResponse({'message': 'Sie sind authentifiziert.'})
  • Wir werden die Behandlung von Mixins später bei der Erklärung von Generic Views oder Berechtigungsmanagements ausführlicher behandeln. Für jetzt ist es ausreichend, zu wissen, dass man Funktionen auf diese Weise kombinieren kann.

5. Einfache Vergleich mit FBV

Typ FBV (Funktionsbasierte Views) CBV (Klassenbasierte Views)
Schreibform Funktionsform Klassen- & Methodenform
HTTP-Methodenverarbeitung if request.method == 'GET': ... else: ... get(), post() usw. nach Methoden getrennt
Möglichkeiten für Code-Duplikationen Bei komplexer Logik ist es leicht, doppelten Code zu erzeugen Wiederverwendung gemeinsamer Logik durch Vererbung, Mixin möglich
Erweiterbarkeit Oft gemischte gemeinsame Logik in einer Funktion Geeignet für komplexe Anforderungen in einer Klassenvererbung
Lesbarkeit Geeignet für einfache Prototypen Umso grösser, desto geeigneter für die Aufrechterhaltung einer klaren Struktur
  • FBV eignet sich gut für kleine oder einfache Funktionen, während CBV Vorteile in Bezug auf Erweiterbarkeit und Wartbarkeit bietet.

  • Insbesondere in Teamprojekten oder mittleren bis großen Projekten ist die Verwendung von CBVs effizient.


6. Etwas tiefer das Thema: dispatch() und URL-Parameter

Django View Anforderungsflussdiagramm

6.1 Gründe für die direkte Übersteuerung von dispatch()

  • Gemeinsame Vor- und Nachbearbeitung: Jederzeit, wenn eine Anfrage eingeht, kann hier die DB-Verbindung überprüft, eine Berechtigungsprüfung durchgeführt oder ein Log erstellt werden.

  • Methoden-Mapping: Intern wird request.method.lower() verwendet, um get(), post(), put() usw. zu finden und aufzurufen. Wenn man zusätzlich Methoden wie PATCH individuell behandeln möchte, kann man dispatch() übersteuern.

class CustomDispatchView(View):
    def dispatch(self, request, *args, **kwargs):
        print("Benutzerdefinierte Vorverarbeitungslogik hier.")
        response = super().dispatch(request, *args, **kwargs)
        print("Benutzerdefinierte Nachverarbeitungslogik hier.")
        return response

6.2 URL-Parameter empfangen

Wenn in urls.py ein Pfadparameter wie <int:user_id>/ angegeben wurde, können die Werte im get()-, post()-Methoden der CBV über kwargs abgerufen werden.

![Django View Struktur im LEGO-Stil](/media/whitedec/blog_img/view_class_lego_structure.webp)# urls.py
urlpatterns = [
    path('user/<int:user_id>/', UserDetailView.as_view(), name='user_detail'),
]

# views.py
class UserDetailView(View):
    def get(self, request, *args, **kwargs):
        user_id = kwargs.get('user_id')
        # Datenbankabfrage mit user_id
        return HttpResponse(f"Benutzer-ID: {user_id}")
  • Ähnlich wie bei FBVs können URL-Parameter aus kwargs entnommen werden.

7. Reichhaltigere praktische Beispiele: Einfaches Boardbeispiel

Für diejenigen, die „Die View-Klasse praktischer nutzen möchten!“, werden wir eine einfache Implementierung eines Boards mit einer Liste und Detailseite vorstellen. (Im nächsten Beitrag, wenn wir Generic Views behandeln, können wir CRUD einfacher umsetzen, aber hier zeigen wir, dass dies auch mit der grundlegenden View-Klasse möglich ist.)

# models.py - Beispielmodell
from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title
# views.py
from django.views import View
from django.shortcuts import render, get_object_or_404
from .models import Post

# Boardartikel Liste
class PostListView(View):
    def get(self, request, *args, **kwargs):
        posts = Post.objects.order_by('-created_at')
        context = {'posts': posts}
        return render(request, 'post_list.html', context)

# Boardartikel Detailansicht
class PostDetailView(View):
    def get(self, request, *args, **kwargs):
        post_id = kwargs.get('pk')
        post = get_object_or_404(Post, pk=post_id)
        context = {'post': post}
        return render(request, 'post_detail.html', context)
<!-- post_list.html -->
<!DOCTYPE html>
<html>
<head>
    <title>Liste der Beiträge</title>
</head>
<body>
    <h1>Liste der Beiträge</h1>
    <ul>
        {% for post in posts %}
            <li>
                <a href="{% url 'post_detail' post.id %}">{{ post.title }}</a>
            </li>
        {% endfor %}
    </ul>
</body>
</html>
<!-- post_detail.html -->
<!DOCTYPE html>
<html>
<head>
    <title>{{ post.title }}</title>
</head>
<body>
    <h1>{{ post.title }}</h1>
    <p>{{ post.content }}</p>
    <p>Erstellt am: {{ post.created_at }}</p>
</body>
</html>
# urls.py
from django.urls import path
from .views import PostListView, PostDetailView

urlpatterns = [
    path('posts/', PostListView.as_view(), name='post_list'),
    path('posts/<int:pk>/', PostDetailView.as_view(), name='post_detail'),
]
  • PostListView: Bei GET-Anfragen werden alle Beiträge abgerufen und an das Template (post_list.html) weitergegeben.

  • PostDetailView: Ein bestimmter Beitrag wird mithilfe des URL-Parameters pk ermittelt und an das Template (post_detail.html) weitergegeben.

  • So lässt sich auch mit der grundlegenden View-Klasse problemlos eine Liste und Detailseite erstellen.

Um jedoch ein vollständiges CRUD-System zu ermöglichen, sind Logiken zum Erstellen/Aktualisieren/Löschen erforderlich. Django bietet die Generic Views, die dies deutlich vereinfachen. Dies wird im nächsten Beitrag ausführlicher behandelt!


8. Fazit und Ausblick auf den nächsten Beitrag

Das war ein Überblick darüber, wie die grundlegende View-Klasse von Django funktioniert und wie sie in der Praxis eingesetzt werden kann. Zusammenfassend lässt sich sagen:

  1. Durch Vererbung von django.views.View sowie die Übersteuerung von Methoden wie get(), post(), dispatch() reagiert man auf HTTP-Anfragen.

  2. Die Verschriftlichung gemeinsamer Logik in der übergeordneten Klasse maximiert die Wiederverwendbarkeit des Codes, indem in den Kind-Views nur die benötigten Teile neu definiert werden.

  3. Man kann einfach View-Logik in vielfältigen Szenarien erstellen, wie zum Beispiel beim Template-Rendering, JSON-Antworten, Datenbankabfragen usw.

  4. Wie im praktischen Beispiel (ein einfaches Board) gezeigt, kann man auch mit der grundlegenden View-Klasse problemlos Projekte erstellen.
    Allerdings ist es wesentlich bequemer, die von Django bereitgestellten Generic Views zu erlernen, um CRUD-Vorgänge zu vereinfachen.

Im nächsten Beitrag widmen wir uns intensiv der FormView-Klasse, die den Prozess der „Erfassung von Benutzereingaben, Validierung, Fehlerbehebung und Umleitung bei Erfolg“ automatisiert.

Die CBV-Serie geht weiter!

  • Teil 3: „Formularverarbeitung einfach mit FormView“
  • Teil 4: „Nutzung von ListView & DetailView“
  • Teil 5: „CRUD-Implementierung mit CreateView, UpdateView, DeleteView“
  • … (weitere folgen)

Frühere Beiträge anzeigen


Zusätzliche Referenzmaterialien

Ich hoffe, dass dieser Beitrag einige Ihrer Fragen zur Struktur und Verwendung der grundlegenden View-Klasse beantwortet hat. Im nächsten Teil lernen wir, wie wir den Prozess des „Erfassens von Formularen → Validierung → Fehlerbehandlung → Umleitung bei Erfolg“ mit FormView vereinfachen können. Ich freue mich über Ihr Interesse!


„Die View-Klasse von Django ist nicht nur ein Werkzeug zur Trennung von Code nach HTTP-Methoden, sondern verbessert auch die Erweiterbarkeit und Wartung in groß angelegten Projekten erheblich.“

Lassen Sie uns weiterhin die CBVs erkunden und produktiver mit Django entwickeln!