APIs im FastAPI-Stil in Django mit Django Ninja erstellen
Takashi Yamamoto
Infrastructure Engineer · Leapcell

Django, ein Fels in der Welt der Webentwicklung, ist bekannt für seine "Batterien inklusive"-Philosophie, die ein umfassendes Framework für den Aufbau robuster Anwendungen bietet. Wenn es jedoch um die API-Entwicklung geht, insbesondere in Szenarien, die hohe Leistung, klare Schema-Definitionen und eine entwicklerfreundliche Erfahrung erfordern, tendieren einige Entwickler zu modernen Frameworks wie FastAPI. FastAPI, gefeiert für seine asynchronen Fähigkeiten, automatische Datenvalidierung und interaktive Dokumentation, die von Pydantic und Type Hints angetrieben wird, bietet einen unglaublich effizienten Workflow. Aber was ist, wenn Sie stark in das Django-Ökosystem investiert sind und diese modernen Paradigmen der API-Entwicklung nutzen möchten, ohne Ihre bestehenden Projekte aufzugeben oder ein völlig neues Ökosystem zu lernen? Hier kommt Django Ninja
ins Spiel. Es bietet eine Brücke, die es Django-Entwicklern ermöglicht, FastAPI-ähnliche, typ-annotierte APIs zu erstellen und von automatischer Validierung, Serialisierung und interaktiver Dokumentation zu profitieren, alles innerhalb der vertrauten Grenzen eines Django-Projekts. Dieser Artikel befasst sich damit, wie Django Ninja
Django-Entwicklern ermöglicht, diese Mischung zu erreichen und das Beste aus beiden Welten zusammenzubringen.
Die moderne API-Entwicklungserfahrung in Django
Bevor wir uns mit den Besonderheiten von Django Ninja
befassen, lassen Sie uns einige Kernbegriffe klären, die diesem modernen Ansatz zur API-Entwicklung zugrunde liegen:
- Type Hinting: In Python 3.5 eingeführt, ermöglichen Type Hints Entwicklern, die erwarteten Typen von Funktionsargumenten und Rückgabewerten zu deklarieren. Obwohl sie Typen zur Laufzeit nicht erzwingen, sind sie für Tools zur statischen Analyse, IDEs und Frameworks wie Pydantic zur Datenvalidierung und Serialisierung von unschätzbarem Wert.
- Pydantic: Eine Bibliothek zur Datenvalidierung und Verwaltung von Einstellungen, die Python-Typannotationen verwendet. Pydantic-Modelle werden verwendet, um das Schema von eingehenden Request-Bodies und ausgehenden Responses zu definieren, Daten automatisch zu validieren und detaillierte Fehlermeldungen zu generieren.
- OpenAPI (früher Swagger): Ein sprachunabhängiger, offener Standard zur Beschreibung von RESTful APIs. Er ermöglicht es Menschen und Computern, die Fähigkeiten eines Dienstes zu entdecken und zu verstehen, ohne Zugriff auf den Quellcode, die Dokumentation oder die Inspektion des Netzwerkverkehrs zu haben.
- Interaktive API-Dokumentation (Swagger UI/ReDoc): Tools, die automatisch visuelle und interaktive Dokumentationen für APIs basierend auf ihrer OpenAPI-Spezifikation generieren. Dies ermöglicht es Entwicklern, API-Endpunkte zu erkunden, Anfragen zu testen und Datenmodelle direkt von einem Webbrowser aus zu verstehen.
- Asynchrone Programmierung (
async
/await
): Ein Programmierparadigma, das die gleichzeitige Ausführung von Aufgaben ermöglicht, ohne den Hauptthread zu blockieren. Dies ist besonders vorteilhaft für I/O-gebundene Operationen (wie Datenbankabfragen oder Aufrufe externer APIs) in Webanwendungen und führt zu verbesserter Leistung und Skalierbarkeit.
Django Ninja
nutzt diese Konzepte, um eine FastAPI-ähnliche Erfahrung innerhalb von Django zu bieten. Es fungiert als Wrapper um Ihre Django Views, interpretiert Type Hints und Pydantic-Modelle, um automatische Datenvalidierung, Serialisierung und OpenAPI-Schema-Generierung durchzuführen.
Erste Schritte mit Django Ninja
Lassen Sie uns ein praktisches Beispiel durchgehen. Wir werden eine einfache API zum Verwalten von "Items" in einem Django-Projekt erstellen.
Stellen Sie zunächst sicher, dass Sie Django installiert und ein Projekt eingerichtet haben. Installieren Sie dann django-ninja
:
pip install django-ninja pydantic
Fügen Sie als Nächstes 'ninja'
zu den INSTALLED_APPS
Ihres Django-Projekts in settings.py
hinzu:
# myproject/settings.py INSTALLED_APPS = [ # ... 'django.contrib.staticfiles', 'ninja', # django-ninja hinzufügen ]
Definieren wir nun ein einfaches Django-Modell für unser Item
:
# myapp/models.py from django.db import models class Item(models.Model): name = models.CharField(max_length=255) description = models.TextField(blank=True) price = models.DecimalField(max_digits=10, decimal_places=2) is_available = models.BooleanField(default=True) def __str__(self): return self.name
Erstellen und wenden Sie Migrationen an:
python manage.py makemigrations myapp python manage.py migrate
API-Endpunkte mit Django Ninja definieren
Der Kern von Django Ninja
liegt in der Definition von API-Routern. Lassen Sie uns eine Datei myapp/api.py
erstellen, um unsere API-Logik unterzubringen.
# myapp/api.py from ninja import NinjaAPI, Schema from typing import List from django.shortcuts import get_object_or_404 from .models import Item api = NinjaAPI() # 1. Pydantic-Schemas für Request Body und Response definieren class ItemIn(Schema): name: str = ... # Erforderliches Feld description: str = None # Optionales Feld price: float is_available: bool = True class ItemOut(Schema): id: int name: str description: str price: float is_available: bool # Optional: Pydantic für die Arbeit mit ORM-Objekten konfigurieren class Config: orm_mode = True # 2. API-Endpunkte mit Type Hints definieren @api.post("/items", response=ItemOut) def create_item(request, item_in: ItemIn): """ Erstellt ein neues Item. """ item = Item.objects.create(**item_in.dict()) return item @api.get("/items", response=List[ItemOut]) def list_items(request): """ Ruft eine Liste aller Items ab. """ return Item.objects.all() @api.get("/items/{item_id}", response=ItemOut) def get_item(request, item_id: int): """ Ruft ein einzelnes Item anhand seiner ID ab. """ item = get_object_or_404(Item, id=item_id) return item @api.put("/items/{item_id}", response=ItemOut) def update_item(request, item_id: int, item_in: ItemIn): """ Aktualisiert ein bestehendes Item. """ item = get_object_or_404(Item, id=item_id) for attr, value in item_in.dict(exclude_unset=True).items(): setattr(item, attr, value) item.save() return item @api.delete("/items/{item_id}", status_code=204) def delete_item(request, item_id: int): """ Löscht ein Item anhand seiner ID. """ item = get_object_or_404(Item, id=item_id) item.delete() return
Integration mit Django URLs
Verbinden Sie schließlich Ihre NinjaAPI
-Instanz mit der urls.py
-Datei Ihres Django-Projekts:
# myproject/urls.py from django.contrib import admin from django.urls import path from myapp.api import api # Importieren Sie Ihre Ninja API-Instanz urlpatterns = [ path('admin/', admin.site.urls), path("api/", api.urls), # Mounten der Ninja API ]
Starten Sie nun Ihren Entwicklungsserver:
python manage.py runserver
Sie können auf die interaktive API-Dokumentation unter http://127.0.0.1:8000/api/docs
(Swagger UI) oder http://127.0.0.1:8000/api/redoc
(ReDoc) zugreifen. Diese Dokumentation wird automatisch basierend auf Ihren ItemIn
- und ItemOut
-Schemas sowie den Type Hints in Ihren API-Endpunktfunktionen generiert.
Demonstrierte Hauptvorteile
- Automatische Datenvalidierung: Wenn Sie eine
POST
-Anfrage an/api/items
senden, validiertDjango Ninja
automatisch den Request Body anhand desItemIn
-Schemas. Wenn ein erforderliches Feld fehlt oder ein falscher Typ vorliegt, wird ein klarer Fehler (422 Unprocessable Entity) mit detaillierten Meldungen zurückgegeben. - Automatische Serialisierung: Wenn Sie ein Django
Item
-Objekt von einem Endpunkt mitresponse=ItemOut
zurückgeben, konvertiertDjango Ninja
es automatisch in ein Dictionary, das demItemOut
-Schema entspricht, und übernimmt die Serialisierung. - Interaktive Dokumentation: Ohne eine einzige Zeile Dokumentation zu schreiben, erhalten Sie voll funktionsfähige interaktive Swagger UI- und ReDoc-Seiten, die es Ihnen ermöglichen, Endpunkte, Datenmodelle zu erkunden und sogar Testanfragen direkt aus dem Browser zu stellen.
- Type Hint-gesteuerte Entwicklung: Die Verwendung von
item_in: ItemIn
unditem_id: int
macht die Eingabe- und Ausgabetypen der API explizit, verbessert die Lesbarkeit und Wartbarkeit des Codes und ermöglicht eine bessere statische Analyse. - Schnelle Entwicklung: Durch die Automatisierung von Validierung und Serialisierung können sich Entwickler mehr auf die Geschäftslogik als auf Boilerplate-Code konzentrieren.
Asynchrone Operationen (Optional)
Django Ninja
unterstützt auch asynchrone View-Funktionen, was natürlich zu den asynchronen Fähigkeiten von Django passt, die in neueren Versionen eingeführt wurden. Um beispielsweise den list_items
-Endpunkt asynchron zu gestalten (vorausgesetzt, Sie haben eine asynchrone ORM oder führen asynchrone I/O-Operationen durch):
# myapp/api.py (Auszug) # ... import asyncio @api.get("/items", response=List[ItemOut]) async def list_items_async(request): """ Ruft eine Liste aller Items asynchron ab. """ # Simuliert eine asynchrone Operation, z.B. einen asynchronen Datenbankaufruf später await asyncio.sleep(0.01) # Hinweis: Django ORM ist standardmäßig synchron. Für echte asynchrone ORM # würden Sie eine Bibliothek wie django-async-orm verwenden oder mit sync_to_async umwandeln return list(Item.objects.all()) # Muss noch verpackt oder async_to_sync verwendet werden
Für eine echte asynchrone Datenbankinteraktion mit Django ORM würden Sie typischerweise sync_to_async
aus asgiref.sync
verwenden oder einen asynchronen ORM-Wrapper. Der Dekorator @api.get()
kann jedoch async def
-Funktionen direkt verarbeiten.
Fortgeschrittene Verwendung und Anwendungsszenarien
Django Ninja
ist hochgradig erweiterbar. Sie können:
- Authentifizierung implementieren: Integration mit dem Authentifizierungssystem von Django oder Verwendung der integrierten
APIKey
- oderJWT
-Authentifizierung vonDjango Ninja
. - Abhängigkeiten hinzufügen: Gemeinsame Abhängigkeiten (wie Datenbanksitzungen, aktueller Benutzer oder externe Clients) in Ihre API-Funktionen injizieren, ähnlich der Abhängigkeitsinjektion von FastAPI.
- Fehlerbehandlung: Benutzerdefinierte Fehlerantworten mit benutzerdefinierten Exception Handlern.
- Router-Organisation: Große APIs in kleinere, modulare Router zur besseren Organisation aufteilen.
- Query- und Path-Parameter: Query- und Path-Parameter einfach über Type Hints definieren und validieren.
Django Ninja
ist ideal für Projekte, die:
- Hohe Leistung von RESTful APIs auf einer bestehenden Django-Anwendung erfordern.
- Starke Typverträge, automatische Datenvalidierung und klare API-Dokumentation schätzen.
- Die besten Vorgehensweisen der FastAPI-Entwicklungserfahrung nutzen möchten, während sie im Django-Ökosystem bleiben.
- Single-Page Applications (SPAs) oder mobile Backends erstellen, bei denen eine saubere, gut dokumentierte API entscheidend ist.
Fazit
Django Ninja
verbindet erfolgreich die robusten, praxiserprobten Fähigkeiten von Django mit den modernen, entwicklerfreundlichen Paradigmen, die von FastAPI eingeführt wurden. Durch die Nutzung von Type Hints und Pydantic bietet es eine elegante und effiziente Möglichkeit, performante, selbstdokumentierende APIs in Ihren Django-Projekten zu erstellen, den Boilerplate-Code drastisch zu reduzieren und die Entwicklungsgeschwindigkeit und Codequalität zu verbessern. Wenn Sie ein Django-Entwickler sind, der Ihr API-Spiel mit einer FastAPI-ähnlichen Erfahrung aufwerten möchte, ist Django Ninja
ein unverzichtbares Werkzeug. Es ermöglicht Ihnen, schöne APIs schnell und mit Vertrauen zu erstellen.