Deep Dive in das Bauen robuster APIs mit Django REST Framework
Lukas Schneider
DevOps Engineer · Leapcell

Einleitung
In der heutigen vernetzten digitalen Landschaft sind Application Programming Interfaces (APIs) die Bausteine, auf denen moderne Anwendungen aufgebaut sind. Ob eine mobile App Daten abruft, eine Single Page Application (SPA) mit einem Backend interagiert oder Dienste miteinander kommunizieren – robuste und effiziente APIs sind von größter Bedeutung. Für Python-Entwickler, die das Django-Framework nutzen, führt das Erstellen solcher APIs oft zum Django REST Framework (DRF). DRF bietet ein leistungsstarkes und flexibles Toolkit, das den Prozess der Erstellung von RESTful APIs erheblich vereinfacht. Dieser Artikel befasst sich eingehend mit den Kernkomponenten von DRF – Serializer, Viewsets und Authentifizierung – und zeigt, wie sie zusammenarbeiten, um die schnelle Entwicklung hochwertiger Webservices zu ermöglichen. Wir werden ihre Prinzipien, Implementierungsdetails und praktischen Anwendungen anhand klarer Codebeispiele untersuchen.
Verstehen der Kernkomponenten von Django REST Framework
Bevor wir uns mit den Details befassen, wollen wir ein grundlegendes Verständnis der Schlüsselbegriffe und Konzepte gewinnen, die für DRF entscheidend sind.
- REST (Representational State Transfer): Ein architektonischer Stil für vernetzte Anwendungen. Er definiert eine Reihe von Einschränkungen, die, wenn sie angewendet werden, zu einem einfachen, skalierbaren und zustandslosen System führen. Zu den Schlüsselprinzipien gehören Ressourcen, Ressourcenidentifizierung (URIs), Ressourcenmanipulation durch Darstellungen und zustandslose Interaktionen.
- API (Application Programming Interface): Eine Reihe definierter Regeln, die es verschiedenen Anwendungen ermöglichen, miteinander zu kommunizieren. Sie gibt an, wie Softwarekomponenten interagieren.
- Serializer: In DRF ist ein Serializer eine Klasse, die es komplexen Datentypen wie Django-Modellinstanzen oder Querysets ermöglicht, in native Python-Datentypen konvertiert zu werden, die dann einfach in JSON, XML oder andere Inhaltstypen gerendert werden können. Umgekehrt bieten Serializer auch Deserialisierung, das Parsen eingehender Daten und deren Validierung anhand vordefinierter Schemata, bevor Modellinstanzen gespeichert oder aktualisiert werden. Sie überbrücken im Wesentlichen die Lücke zwischen Python-Objekten und API-Datenrepräsentationen.
- Viewset: Ein Viewset ist eine Art klassenbasierte Ansicht, die eine Implementierung für die Standardaktionen einer Ressource bereitstellt, wie z. B.
list
,retrieve
,create
,update
,partial_update
unddestroy
. Durch die Verwendung von Viewsets können Sie eine Reihe zusammengehöriger Ansichten in einer einzigen Klasse zusammenfassen, wodurch Ihre URLs und Ihre Logik prägnanter und wartbarer werden. Sie arbeiten mit Routern zusammen, um URL-Muster automatisch zu generieren. - Authentifizierung: Der Prozess der Überprüfung der Identität eines Benutzers oder Clients. In DRF bestimmen Authentifizierungsschemata, wer eine Anfrage stellt. DRF bietet verschiedene Authentifizierungsklassen (z. B. Token, Session, Basic), die problemlos in Ansichten oder Viewsets integriert werden können, um Ihre API-Endpunkte zu sichern.
- Berechtigungen: Der Prozess der Bestimmung, was ein authentifizierter Benutzer oder Client tun darf. Sobald ein Benutzer authentifiziert ist, entscheiden Berechtigungsklassen in DRF, ob der Benutzer die Erlaubnis hat, eine bestimmte Aktion für eine gegebene Ressource auszuführen.
Serializer: Die Datentransformationsschicht
Serializer sind vielleicht der grundlegendste Baustein in DRF und fungieren als Übersetzer zwischen Ihren Python-Objekten/Datenbankmodellen und den Datenformaten, die von Ihren API-Clients verwendet werden.
Prinzip und Implementierung
Serializer sind für zwei Hauptoperationen konzipiert:
- Serialisierung: Konvertierung von Python-Objekten (wie Django-Modellinstanzen) in Formate wie JSON oder XML für API-Antworten.
- Deserialisierung: Validierung eingehender Daten von API-Anfragen und Konvertierung in Python-Objekte für Datenbankinteraktionen.
DRF bietet verschiedene Arten von Serializern, wobei ModelSerializer
am häufigsten für die direkte Zuordnung zu Django-Modellen verwendet wird.
Beispielszenario: Eine einfache Blog-Post-API
Stellen wir uns vor, wir haben ein Post
-Modell in unserer Django-Anwendung:
# blog/models.py from django.db import models from django.contrib.auth.models import User class Post(models.Model): title = models.CharField(max_length=200) content = models.TextField() author = models.ForeignKey(User, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) def __str__(self): return self.title
Nun erstellen wir einen Serializer für dieses Post
-Modell.
# blog/serializers.py from rest_framework import serializers from .models import Post class PostSerializer(serializers.ModelSerializer): author = serializers.ReadOnlyField(source='author.username') # Zeigt den Benutzernamen anstelle der ID an class Meta: model = Post fields = ['id', 'title', 'content', 'author', 'created_at', 'updated_at'] read_only_fields = ['created_at', 'updated_at'] # Diese Felder werden vom Server gesetzt
In diesem PostSerializer
:
serializers.ModelSerializer
leitet automatisch Felder aus demPost
-Modell ab.author = serializers.ReadOnlyField(source='author.username')
passt das Feldauthor
an, um den Benutzernamen des Autors anstelle des Primärschlüssels anzuzeigen, und macht es schreibgeschützt.fields
listet explizit die einzubindenden Felder auf.read_only_fields
markiert bestimmte Felder als schreibgeschützt und verhindert, dass Clients sie direkt ändern.
Anwendung
Wenn ein Post
-Objekt an einen Client gesendet werden muss, wandelt der PostSerializer
es in ein Dictionary um, das dann als JSON gerendert werden kann. Wenn ein Client JSON-Daten sendet, um einen Post
zu erstellen oder zu aktualisieren, validiert der Serializer diese Daten anhand der definierten Felder und Datentypen, bevor sie in die Datenbank gespeichert werden können.
Viewsets: Orchestrierung von API-Endpunkten
Viewsets bieten eine höhere Abstraktionsebene über Standard-Django-Ansichten und ermöglichen es Ihnen, das Verhalten der API für eine Ressource in einer einzigen Klasse zu definieren.
Prinzip und Implementierung
Anstatt separate list
, create
, retrieve
, update
und destroy
-Ansichten zu schreiben, kombiniert ein Viewset diese Operationen. Dieser Ansatz, insbesondere in Verbindung mit den Routern von DRF, reduziert den Boilerplate-Code erheblich.
Beispiel: Integration eines Serializers mit einem Viewset
# blog/views.py from rest_framework import viewsets from rest_framework import permissions # Berechtigungen importieren from .models import Post from .serializers import PostSerializer class PostViewSet(viewsets.ModelViewSet): queryset = Post.objects.all().order_by('-created_at') serializer_class = PostSerializer permission_classes = [permissions.IsAuthenticatedOrReadOnly] # Standardberechtigung def perform_create(self, serializer): serializer.save(author=self.request.user) # Den angemeldeten Benutzer als Autor zuweisen
Und dann die Verknüpfung in urls.py
:
# drf_project/urls.py (Ihre Haupt-URLconf des Projekts) from django.contrib import admin from django.urls import path, include from rest_framework.routers import DefaultRouter from blog.views import PostViewSet router = DefaultRouter() router.register(r'posts', PostViewSet) urlpatterns = [ path('admin/', admin.site.urls), path('api/', include(router.urls)), ]
In PostViewSet
:
queryset
definiert die Basisverfügbarkeit für das Abrufen von Objekten.serializer_class
verknüpft denPostViewSet
mit unseremPostSerializer
.permission_classes
definiert, wer auf diese Ressourcen zugreifen und sie ändern darf (mehr dazu später).perform_create(self, serializer)
ist eine überschriebene Methode, die es uns ermöglicht, beim Erstellen von Objekten benutzerdefinierte Logik einzuschleusen, in diesem Fall die automatische Zuweisung des Autors eines neuen Beitrags zum aktuell angemeldeten Benutzer.
Durch die Verwendung von routers.DefaultRouter
generiert DRF automatisch URLs für alle Standard-CRUD-Operationen für den Endpunkt posts
(z. B. /api/posts/
für Liste/Erstellung, /api/posts/<id>/
für Abruf/Aktualisierung/Löschung).
Anwendung
Diese Einrichtung ermöglicht es Entwicklern, mit minimalem Code schnell vollständige CRUD-Funktionalität für ein Modell bereitzustellen. Sie folgt den DRY-Prinzipien (Don't Repeat Yourself) und vereinfacht die Verwaltung von API-Endpunkten, insbesondere in Anwendungen mit vielen Ressourcen.
Authentifizierung: Absichern Ihrer APIs
Authentifizierung ist die erste Verteidigungslinie Ihrer API und überprüft die Identität des Clients, der versucht, auf Ressourcen zuzugreifen.
Prinzip und Implementierung
Das Authentifizierungssystem von DRF ist steckbar, sodass Sie problemlos zwischen verschiedenen Authentifizierungsschemata wechseln oder diese kombinieren können. Wenn eine Anfrage eingeht, durchläuft DRF die definierten Authentifizierungsklassen, bis eine die Anfrage erfolgreich authentifiziert hat.
Zu den gängigen DRF-Authentifizierungsschemata gehören:
- SessionAuthentication: Ideal für browserbasierte Clients, die das Sitzungssystem von Django verwenden.
- TokenAuthentication: Eine beliebte Wahl für mobile und SPA-Clients, bei denen ein eindeutiges Token mit jeder Anfrage gesendet wird.
- BasicAuthentication: Sendet Benutzername/Passwort-Anmeldeinformationen mit jeder Anfrage, typischerweise über HTTPS.
Integrieren wir die Token-basierte Authentifizierung.
1. Fügen Sie rest_framework.authtoken
zu INSTALLED_APPS
hinzu:
# drf_project/settings.py INSTALLED_APPS = [ # ... 'rest_framework', 'rest_framework.authtoken', # Für TokenAuthentication # ... ]
2. Konfigurieren Sie die DRF-Authentifizierung:
# drf_project/settings.py REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', 'rest_framework.authentication.SessionAuthentication', # Optional, für den Zugriff auf Browser-APIs ], 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', # Standardmäßig ist die Authentifizierung erforderlich ] }
3. Generieren Sie Token für Benutzer (z. B. bei Benutzererstellung oder Anmeldung):
# Möglicherweise fügen Sie einen Endpunkt zur Token-Generierung hinzu # blog/views.py (oder eine dedizierte Authentifizierungs-App) from rest_framework.authtoken.views import ObtainAuthToken from rest_framework.authtoken.models import Token from rest_framework.response import Response class CustomAuthToken(ObtainAuthToken): """ Benutzerdefinierte Ansicht zum Erhalt des Authentifizierungstokens. Bei erfolgreicher Anmeldung werden Benutzer-ID und Token zurückgegeben. """ def post(self, request, *args, **kwargs): serializer = self.serializer_class(data=request.data, context={'request': request}) serializer.is_valid(raise_exception=True) user = serializer.validated_data['user'] token, created = Token.objects.get_or_create(user=user) return Response({ 'token': token.key, 'user_id': user.pk, 'email': user.email }) # drf_project/urls.py # ... from blog.views import CustomAuthToken # ... urlpatterns = [ # ... path('api/token-auth/', CustomAuthToken.as_view()), ]
Jetzt kann ein Client ein Token erhalten, indem er eine POST-Anfrage an /api/token-auth/
mit Benutzername und Passwort sendet. Nachfolgende Anfragen enthalten den Header Authorization: Token <your_token_key>
.
Anwendung
Authentifizierung ist entscheidend für den Schutz sensibler Daten und die Kontrolle des Zugriffs auf API-Funktionen. Egal, ob Sie eine öffentliche API mit Ratenbegrenzung oder einen privaten internen Dienst erstellen, eine robuste Authentifizierung stellt sicher, dass nur autorisierte Benutzer mit Ihrem System interagieren können.
Berechtigungen: Granulare Zugriffskontrolle
Nachdem ein Benutzer authentifiziert wurde, bestimmen Berechtigungsklassen, auf welche Ressourcen er zugreifen und welche Vorgänge er ausführen darf.
Prinzip und Implementierung
Das Berechtigungssystem von DRF ermöglicht eine feingranulare Kontrolle. Berechtigungsklassen werden nach der Authentifizierung angewendet und für jede eingehende Anfrage ausgewertet.
Beispiel: Benutzerdefinierte Berechtigungen
Wir haben permissions.IsAuthenticatedOrReadOnly
in unserem PostViewSet
verwendet, was bedeutet, dass authentifizierte Benutzer jede Aktion ausführen können, während nicht authentifizierte Benutzer nur lesen können (GET, HEAD, OPTIONS).
Lassen Sie uns eine benutzerdefinierte Berechtigung erstellen, die nur dem Autor eines Beitrags erlaubt, ihn zu bearbeiten/löschen.
# blog/permissions.py from rest_framework import permissions class IsAuthorOrReadOnly(permissions.BasePermission): """ Benutzerdefinierte Berechtigung, nur Autoren eines Objekts zu gestatten, es zu bearbeiten. """ def has_object_permission(self, request, view, obj): # Lese-Berechtigungen sind für jede Anfrage erlaubt, # daher erlauben wir immer GET-, HEAD- oder OPTIONS-Anfragen. if request.method in permissions.SAFE_METHODS: return True # Schreib-Berechtigungen sind nur dem Autor des Beitrags erlaubt. return obj.author == request.user
Aktualisieren Sie nun PostViewSet
, um diese benutzerdefinierte Berechtigung zu verwenden:
# blog/views.py # ... from .permissions import IsAuthorOrReadOnly # Die benutzerdefinierte Berechtigung importieren class PostViewSet(viewsets.ModelViewSet): queryset = Post.objects.all().order_by('-created_at') serializer_class = PostSerializer permission_classes = [IsAuthorOrReadOnly] # Die benutzerdefinierte Berechtigung verwenden # ... (die perform_create-Methode bleibt gleich)
Anwendung
Benutzerdefinierte Berechtigungen sind von unschätzbarem Wert für die Implementierung komplexer Geschäftslogik rund um die Zugriffskontrolle. Sie stellen sicher, dass Benutzer nur mit Daten und Funktionalitäten interagieren, für die sie autorisiert sind, und verbessern so die Sicherheit und Integrität Ihrer API.
Fazit
Django REST Framework ermöglicht es Entwicklern, leistungsstarke, skalierbare und sichere Webservices mit bemerkenswerter Effizienz zu erstellen. Durch das Verständnis und die effektive Nutzung seiner Kernkomponenten – Serializer für die Datentransformation, Viewsets für die optimierte Erstellung von API-Endpunkten und ein robustes System für Authentifizierung und Berechtigungen – können Sie APIs entwickeln, die sowohl hochfunktional als auch einfach zu warten sind. DRF bietet die wesentlichen Werkzeuge, um Ihre Datenmodelle in dynamische API-Ressourcen zu übersetzen, die für eine Vielzahl von Client-Anwendungen bereit sind.