# Views (Kurzübersicht)
Es gibt in Django zwei Haupttypen von Views, **Function-Based Views** und **Class-Based-Views**.
***Hinweis:*** Einige der folgenden Views existieren nur im Django REST Framework (DRF) und dienen der API-Entwicklung; die klassischen Django-Views funktionieren auch ohne DRF.
# 1. **Function-Based Views (FBVs)**
- Definiert als einfache Python-Funktionen.
- Reagieren direkt auf HTTP-Anfragen (`request`).
- Ideal für **einfache und schnelle Implementierungen**.
**Beispiel (Django):**
```python
def my_view(request):
return HttpResponse("Hello, world!")
```
Im Kontext von **Django REST Framework (DRF)** kann der `@api_view`-Dekorator verwendet werden, um eine Funktion als API-View zu kennzeichnen:
**Beispiel (DRF-only):**
```python
from rest_framework.decorators import api_view
from rest_framework.response import Response
@api_view(['GET'])
def my_api_view(request):
return Response({"message": "Hello, API World!"})
```
- Der `@api_view`-Dekorator ermöglicht es, dass meine Funktion als API-Endpoint fungiert, der JSON-Antworten zurückgibt und die richtigen HTTP-Methoden verarbeitet.
# 2. **Class-Based Views (CBVs)**
- Basieren auf Python-Klassen und erben meist von `View` oder anderen Django-View-Klassen.
- Verwenden Methoden wie `get()`, `post()`, etc., um unterschiedliche HTTP-Methoden zu behandeln.
- Gut geeignet für **strukturierte, wiederverwendbare und erweiterbare** Views.
**Beispiel (Django):**
```python
from django.views import View
from django.http import HttpResponse
class MyView(View):
def get(self, request):
return HttpResponse("Hello, world!")
```
**Beispiel (DRF-only):**
```python
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class MyAPIView(APIView):
def get(self, request, format=None):
return Response({"message": "Hello, DRF world!"}, status=status.HTTP_200_OK)
```
## Erweiterung von CBVs
### a) **Generic Class-Based Views (GCBVs)**
- Vorgefertigte CBVs für häufige und große Aufgaben (CRUD).
- Reduzieren Boilerplate-Code.
**Beispiele (Django):**
- `ListView`: Liste von Objekten anzeigen
- `DetailView`: Einzelnes Objekt anzeigen
- `CreateView`: Neues Objekt erstellen
- `UpdateView`: Vorhandenes Objekt bearbeiten
- `DeleteView`: Objekt löschen
- `TemplateView`: Rendert hauptsächlich ein Template, oft ohne komplexe Logik
- `RedirectView`: Leitet Benutzer automatisch zu einer anderen URL weiter
**GenericAPIView – DRF-Basis:**
- `GenericAPIView` ist die **Basisklasse** aller DRF-Generic-Views.
- Erweitert `APIView` um zusätzliche, nützliche Funktionalitäten:
- **Querysets:** `queryset`Attribut oder `get_queryset()`Methode
- **Serializer:** `serializer_class`Attribut oder `get_serializer()`
- **Pagination**, **Filtering**, **Ordering**, **Searching**
- Wird selten direkt verwendet, sondern meist **in Kombination mit Mixins** oder durch die spezifischen Generics (z. B. `ListAPIView`).
```bash
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from .models import Employee
from .serializers import EmployeeSerializer
class EmployeeGenericView(GenericAPIView):
queryset = Employee.objects.all()
serializer_class = EmployeeSerializer
def get(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
```
Auf der `GenericAPIView` basieren mehrere spezialisierte **Generic Views**, die jeweils typische CRUD-Operationen kapseln und oft in API-Projekten direkt verwendet werden.
**Beispiele (DRF-only):**
- `ListAPIView`: Liste von Objekten anzeigen (als JSON)
- `DetailAPIView`: Einzelnes Objekt anzeigen (als JSON)
- `CreateAPIView`: Neues Objekt erstellen (POST)
- `UpdateAPIView`: Vorhandenes Objekt bearbeiten (PUT/PATCH)
- `DestroyAPIView`: Objekt löschen (DELETE)
- `RetrieveUpdateDestroyAPIView`: Einzelnes Objekt abrufen, bearbeiten und löschen (GET, PUT/PATCH, DELETE)
- `ListCreateAPIView`: Liste von Objekten anzeigen (GET) und neues Objekt erstellen (POST)
**Beispiel (DRF-only):**
```python
from rest_framework.generics import ListAPIView
from .models import Employee
from .serializers import EmployeeSerializer
class EmployeeListAPIView(ListAPIView):
queryset = Employee.objects.all()
serializer_class = EmployeeSerializer
```
### b) **Mixins (DRF-only)**
- **Wiederverwendbare Klassen**, die spezifische Funktionalität (z. B. Create, Update, Delete) einbringen.
- Besonders nützlich in Kombination mit `GenericAPIView`. Generic Views übernehmen die “großen” Aufgaben, während Mixins die “kleinen” Aufgaben übernehmen.
**Häufige Mixins (DRF-only):**
- `ListModelMixin`: `GET` – Liste anzeigen
- `CreateModelMixin`: `POST` – Objekt erstellen
- `RetrieveModelMixin`: `GET` – Einzelnes Objekt holen
- `UpdateModelMixin`: `PUT/PATCH` – Objekt aktualisieren
- `DestroyModelMixin`: `DELETE` – Objekt löschen
**Beispiel (DRF-only):**
```python
from rest_framework import mixins, generics
from .models import Employee
from .serializers import EmployeeSerializer
class EmployeeListCreateView(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Employee.objects.all()
serializer_class = EmployeeSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
```
### **c) Viewsets (DRF-only)**
- Möchte ich nur Standard-CRUD-Operationen durchführen, kann ich auch einfach mit **Viewsets** arbeiten. Sie bündeln viele der Methoden von **Mixins** und **Generic Views** in einer einzigen Klasse. Das bedeutet, dass ich nicht jede Methode wie `list()`, `create()`, `retrieve()`, `update()` und `destroy()` manuell definieren muss – das übernimmt das Viewset automatisch.
- Ein `Router` wie `SimpleRouter` oder `DefaultRouter` **generiert automatisch die URL-Routen** für alle Methoden, die mein `ViewSet` bereitstellt. Alternativ kann ich die URL-Routen auch manuell mit `.as_view()` zuweisen, wenn ich keinen Router nutzen möchte.
- Das häufigst verwendete Viewset ist das `ModelViewSet` , welches automatisch alle wichtigen CRUD-Methoden inkl. einer **DetailView** zur Verfügung stellt:
**Beispiel (DRF-only):**
```python
from rest_framework import viewsets
from .models import Employee
from .serializers import EmployeeSerializer
class EmployeeViewSet(viewsets.ModelViewSet):
queryset = Employee.objects.all()
serializer_class = EmployeeSerializer
```
- **Viewsets können auch mit Mixins kombiniert werden**, wenn ich gezielt nur bestimmte Methoden (z. B. nur `list` und `retrieve`) bereitstellen möchte. In diesem Fall verwende ich statt `ModelViewSet` gezielt einzelne Mixins in Kombination mit `GenericViewSet`.
**Beispiel mit Mixins (DRF-only):**
```python
from rest_framework import viewsets, mixins
from .models import Employee
from .serializers import EmployeeSerializer
class EmployeeReadOnlyViewSet(mixins.ListModelMixin,
mixins.RetrieveModelMixin,
viewsets.GenericViewSet):
queryset = Employee.objects.all()
serializer_class = EmployeeSerializer
```