Inhaltsverzeichnis
- Django Ninja vs FastAPI: Ein detaillierter Vergleich zweier moderner Python Web-Frameworks
- Schnellübersicht: Django Ninja vs. FastAPI auf einen Blick
- Die Grundidee hinter beiden Frameworks
- Setup-Vergleich: Der erste Eindruck zählt
- Model Schemas: Der größte Unterschied
- Endpoint-Definition: Subtile aber wichtige Unterschiede
- Middlewares und Lifecycles: Verschiedene Philosophien
- Automatische Dokumentationsgenerierung: Beide glänzen
- Authentifizierung & Sicherheit in der Praxis
- Projektstruktur und Deployment
- Praktische Pro-Tipps
- Fazit: Wann solltest du welches Framework wählen?
- Häufig gestellte Fragen (FAQs)
Über den Autor
23.07.2025
Ein detaillierter Vergleich zweier moderner API-FrameworksDjango Ninja vs. FastAPI: Ein detaillierter Vergleich
FastAPI hat die Python-Webentwicklung revolutioniert – doch mit Django Ninja gibt es eine Alternative, die das Beste aus zwei Welten vereint.
Während FastAPI mit seiner modernen, asynchronen Architektur und maximaler Flexibilität punktet, bringt Django Ninja die elegante API-Syntax von FastAPI in das bewährte Django-Ökosystem. In diesem umfassenden Vergleich erfährst du nicht nur die technischen Unterschiede bei Setup, Schema-Definitionen und Middleware-Konzepten, sondern erhältst auch eine fundierte Entscheidungshilfe: Wann ist die radikale Freiheit von FastAPI der richtige Weg, und wann profitierst du mehr von Django Ninjas nahtloser Integration in die Django-Welt?
Django Ninja vs FastAPI: Ein detaillierter Vergleich zweier moderner Python Web-Frameworks
Wenn du moderne REST APIs in Python entwickeln möchtest, stößt du unweigerlich auf FastAPI - das Framework, das die Python-Web-Entwicklung in den letzten Jahren revolutioniert hat. Aber kennst du auch Django Ninja? Diese elegante Alternative bringt die Geschwindigkeit und Type-Safety von FastAPI in die Django-Welt. Lass uns gemeinsam erkunden, wie sich diese beiden Frameworks unterscheiden und wann du welches einsetzen solltest.
Schnellübersicht: Django Ninja vs. FastAPI auf einen Blick
Feature | Django Ninja | FastAPI |
---|---|---|
Grundlage | Auf Django aufgebaut | Eigenständiges Framework (basiert auf Starlette) |
Performance | Sehr gut, aber synchron | Exzellent, primär asynchron (ASGI) |
Datenbank | Django ORM (integriert) | Jedes ORM (z.B. SQLAlchemy, Tortoise ORM) |
Admin-Panel | Django Admin (out-of-the-box) | Muss selbst gebaut/integriert werden |
Authentifizierung | Django Auth (integriert) | Muss selbst implementiert werden |
Lernkurve | Sehr flach für Django-Entwickler | Flach für Python-Entwickler |
Flexibilität | Weniger flexibel, aber "batteries-included" | Maximale Flexibilität, aber mehr Setup-Aufwand |
Ideal für | Bestehende Django-Projekte, schnelle CRUD-APIs | Hochperformante Microservices, neue Projekte |
Die Grundidee hinter beiden Frameworks
Bevor wir in die technischen Details eintauchen, lasst mich kurz erklären, was beide Frameworks besonders macht. FastAPI ist ein eigenständiges, asynchrones Web-Framework, das von Grund auf für moderne API-Entwicklung konzipiert wurde. Django Ninja hingegen ist eine Erweiterung für Django, die es erlaubt, APIs mit einer FastAPI-ähnlichen Syntax zu schreiben, während du weiterhin das gesamte Django-Ökosystem nutzen kannst.
Setup-Vergleich: Der erste Eindruck zählt
FastAPI Setup
Bei FastAPI beginnst du praktisch bei null. Das hat Vor- und Nachteile. Der Vorteil ist die absolute Freiheit - du entscheidest über jeden Aspekt deiner Anwendung. Ein minimales FastAPI-Projekt sieht so aus:
# main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
# Starten mit: fastapi dev main.py
Das war's! Mit nur wenigen Zeilen hast du eine funktionierende API. Aber sobald du Datenbanken, Authentifizierung oder andere Features brauchst, musst du alles selbst konfigurieren:
# Ein realistischeres FastAPI Setup
from fastapi import FastAPI
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
import uvicorn
# Datenbank Setup
SQLALCHEMY_DATABASE_URL = "postgresql://user:password@localhost/dbname"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
app = FastAPI(title="Meine API", version="1.0.0")
# Dependency für Datenbank-Sessions
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
Django Ninja Setup
Bei Django Ninja hast du bereits ein vollständiges Django-Projekt als Grundlage. Das bedeutet, dass Datenbank-Konfiguration, Migrationen, Admin-Interface und vieles mehr bereits vorhanden sind:
# Nach django-admin startproject und pip install django-ninja
# views.py
from ninja import NinjaAPI
api = NinjaAPI()
@api.get("/hello")
def hello(request):
return {"message": "Hello from Django Ninja"}
# urls.py
from django.urls import path
from my_app.views import api
urlpatterns = [
path("api/", api.urls),
]
Der große Unterschied? Mit Django Ninja bekommst du das Beste aus beiden Welten: Die intuitive API-Syntax von FastAPI und die bewährte Infrastruktur von Django. Du musst nicht bei null anfangen, sondern baust auf einem soliden Fundament auf.
Model Schemas: Der größte Unterschied
Hier wird es richtig interessant! Beide Frameworks nutzen Python Type Hints für die Validierung, aber die Implementierung unterscheidet sich fundamental.
FastAPI mit Pydantic
FastAPI setzt vollständig auf Pydantic für die Datenvalidierung. Pydantic-Modelle sind eigenständige Klassen, die deine Datenstrukturen definieren:
from pydantic import BaseModel, Field, validator
from datetime import datetime
class UserBase(BaseModel):
# es gibt auch eine E-Mail Klasse in Pydantic!
email: str = Field(..., description="Die E-Mail-Adresse des Benutzers")
username: str = Field(..., min_length=3, max_length=20)
@validator('email')
def email_must_be_valid(cls, v):
if '@' not in v:
raise ValueError('Keine gültige E-Mail-Adresse')
return v
class UserCreate(UserBase):
password: str = Field(..., min_length=8)
class UserResponse(UserBase):
id: int
created_at: datetime
is_active: bool = True
class Config:
# Erlaubt die Verwendung von ORM-Objekten
orm_mode = True
Die Stärke von Pydantic liegt in seiner Flexibilität und den umfangreichen Validierungsmöglichkeiten. Du kannst komplexe Validierungslogik implementieren, automatische Konvertierungen durchführen und sogar verschachtelte Modelle erstellen.
Django Ninja's Schema-System
Django Ninja bietet dir zwei Möglichkeiten: Du kannst entweder Pydantic verwenden oder Ninja's eigenes Schema-System. Das Schema-System von Ninja ist speziell für die Integration mit Django ORM optimiert:
from ninja import Schema, ModelSchema
from django.contrib.auth.models import User
from typing import Optional
# Option 1: Manuelles Schema
class UserSchema(Schema):
id: int
username: str
email: str
first_name: Optional[str] = None
last_name: Optional[str] = None
# Option 2: ModelSchema - Automatisch aus Django Model
class UserModelSchema(ModelSchema):
class Config:
model = User
model_fields = ['id', 'username', 'email', 'first_name', 'last_name']
# Option 3: Erweiterte ModelSchema mit zusätzlichen Feldern
class UserDetailSchema(ModelSchema):
full_name: str
post_count: int = 0
class Config:
model = User
model_fields = '__all__'
@staticmethod
def resolve_full_name(obj):
return f"{obj.first_name} {obj.last_name}"
Der entscheidende Vorteil von Django Ninja's Schema-System ist die nahtlose Integration mit Django Models. Du musst nicht ständig zwischen ORM-Objekten und Pydantic-Modellen konvertieren. Die ModelSchema
Klasse generiert automatisch Schemas basierend auf deinen Django Models, was Duplikation vermeidet.
Der tiefere Vergleich: Pydantic vs Ninja Schema
Lass uns die "philosophischen" Unterschiede verstehen:
Pydantic in FastAPI:
- Vollständig entkoppelt von der Datenbank
- Explizite Konvertierung zwischen ORM und Pydantic nötig
- Mehr Kontrolle, aber auch mehr Boilerplate
- Perfekt für komplexe Validierungen und Transformationen
# FastAPI mit SQLAlchemy
@app.post("/users/", response_model=UserResponse)
def create_user(user: UserCreate, db: Session = Depends(get_db)):
# Manuelle Konvertierung nötig
db_user = UserModel(
email=user.email,
username=user.username,
hashed_password=hash_password(user.password)
)
db.add(db_user)
db.commit()
db.refresh(db_user)
# Pydantic konvertiert automatisch dank orm_mode
return db_user
Ninja Schema:
- Eng mit Django ORM verzahnt
- Automatische Konvertierung zwischen Django Models und Schemas
- Weniger Code, aber auch weniger Flexibilität bei Bedarf
- Ideal für CRUD-Operationen mit Django Models
# Django Ninja
@api.post("/users/", response=UserModelSchema)
def create_user(request, user_data: UserCreateSchema):
# Direkte Arbeit mit Django ORM
user = User.objects.create_user(
username=user_data.username,
email=user_data.email,
password=user_data.password
)
# Automatische Konvertierung zum Response Schema
return user
Endpoint-Definition: Subtile aber wichtige Unterschiede
Auf den ersten Blick sehen die Endpoint-Definitionen sehr ähnlich aus, aber der Teufel steckt im Detail.
FastAPI Endpoints
from fastapi import FastAPI, Path, Query, Body, Header, Depends
from typing import Optional, List
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(
item_id: int = Path(..., title="Die ID des Items", ge=1),
q: Optional[str] = Query(None, max_length=50),
x_token: str = Header(...),
current_user: User = Depends(get_current_user)
):
# Async ist optional aber empfohlen
return {"item_id": item_id, "q": q}
@app.post("/items/")
async def create_item(
item: Item = Body(..., embed=True),
importance: int = Body(...)
):
return {"item": item, "importance": importance}
Django Ninja Endpoints
from ninja import Router, Path, Query, Body, Header
from django.shortcuts import get_object_or_404
router = Router()
@router.get("/items/{item_id}")
def read_item(
request, # Django Request Objekt ist immer der erste Parameter
item_id: int = Path(..., title="Die ID des Items", ge=1),
q: Optional[str] = Query(None, max_length=50),
x_token: str = Header(...)
):
# Nutze Django's ORM direkt
item = get_object_or_404(Item, id=item_id)
return {"item_id": item.id, "q": q}
@router.post("/items/", response=ItemSchema)
def create_item(request, item_data: ItemCreateSchema):
# Django's Authentifizierung ist direkt verfügbar
if not request.user.is_authenticated:
return 401, {"detail": "Not authenticated"}
item = Item.objects.create(**item_data.dict(), owner=request.user)
return item
Die wichtigsten Unterschiede:
- Request-Objekt: Django Ninja übergibt immer das Django Request-Objekt als ersten Parameter. Das gibt dir Zugriff auf Sessions, User-Objekt und andere Django-Features.
- Async-Support: FastAPI ist von Grund auf async, während Django Ninja primär synchron arbeitet (async Support ist experimentell).
- Response-Handling: Django Ninja erlaubt es dir, direkt Django Model-Instanzen zurückzugeben, während FastAPI explizite Konvertierung benötigt.
Middlewares und Lifecycles: Verschiedene Philosophien
FastAPI Middleware und Lifecycle
FastAPI bietet ein minimalistisches aber mächtiges Middleware-System:
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
import time
app = FastAPI()
# CORS Middleware
app.add_middleware(
CORSMiddleware,
# ! ACHTUNG: never ever in Production !
allow_origins=["*"],
allow_methods=["*"],
allow_headers=["*"],
)
# Custom Middleware
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
return response
# Lifecycle Events
@app.on_event("startup")
async def startup_event():
# Initialisierung, z.B. Datenbankverbindung
print("Starting up...")
@app.on_event("shutdown")
async def shutdown_event():
# Aufräumen
print("Shutting down...")
Django Ninja Middleware
Django Ninja nutzt das bewährte Django Middleware-System:
# Django Middleware (in middleware.py)
class ProcessTimeMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
start_time = time.time()
response = self.get_response(request)
process_time = time.time() - start_time
response['X-Process-Time'] = str(process_time)
return response
# In settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'myapp.middleware.ProcessTimeMiddleware',
# ... andere Middlewares
]
# Django Ninja spezifische Features
from ninja import NinjaAPI
api = NinjaAPI()
# API-Level Middleware/Hooks
@api.exception_handler(ValidationError)
def validation_error_handler(request, exc):
return api.create_response(
request,
{"detail": exc.errors()},
status=422
)
Der Hauptunterschied liegt in der Philosophie: FastAPI gibt dir ein leeres Blatt und du baust deine Middleware-Pipeline selbst auf. Django hingegen kommt mit einer umfangreichen Middleware-Sammlung (Security, Session, CSRF, etc.), die du bei Django Ninja automatisch nutzen kannst.
Automatische Dokumentationsgenerierung: Beide glänzen
Sowohl FastAPI als auch Django Ninja generieren automatisch interaktive API-Dokumentation. Aber es gibt feine Unterschiede.
FastAPI Dokumentation
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI(
title="Meine tolle API",
description="Das ist eine ausführliche Beschreibung meiner API",
version="2.5.0",
terms_of_service="https://blueshoe.de/terms/",
contact={
"name": "API Support",
"email": "support@blueshoe.de"
}
)
class Item(BaseModel):
"""Ein Item in unserem System"""
name: str = Field(..., example="Beispiel Item", description="Der Name des Items")
price: float = Field(..., gt=0, example=29.99, description="Preis in EUR")
tax: Optional[float] = Field(None, example=2.5)
@app.post(
"/items/",
response_model=Item,
summary="Erstelle ein neues Item",
description="Erstelle ein neues Item mit allen Details",
response_description="Das erstellte Item",
tags=["items"]
)
async def create_item(item: Item):
"""
Erstelle ein Item mit allen Informationen:
- **name**: Eindeutiger Name des Items
- **price**: Preis muss größer als 0 sein
- **tax**: Optionale Steuerangabe
"""
# Tatsächlicher Code ....
return item
FastAPI generiert sowohl Swagger UI (unter /docs
) als auch ReDoc (unter /redoc
). Die Dokumentation ist hochgradig anpassbar und nutzt die Pydantic-Modelle für Beispiele.
Django Ninja Dokumentation
from ninja import NinjaAPI, Schema
from typing import Optional
api = NinjaAPI(
title="Django Ninja API",
version="1.0.0",
description="Meine Django-basierte API"
)
class ItemSchema(Schema):
"""Schema für Items"""
name: str = Field(..., example="Beispiel Item")
price: float = Field(..., gt=0, example=29.99)
tax: Optional[float] = None
class Config:
schema_extra = {
"example": {
"name": "Tolles Produkt",
"price": 49.99,
"tax": 3.5
}
}
@api.post(
"/items/",
response=ItemSchema,
summary="Erstelle ein neues Item",
tags=["items"],
operation_id="create_item"
)
def create_item(request, item: ItemSchema):
"""
Erstelle ein neues Item.
Diese Funktion speichert das Item in der Django-Datenbank.
"""
# Tatsächlicher Code ....
return item
Django Ninja generiert ebenfalls eine Swagger UI (standardmäßig unter /api/docs
). Ein Vorteil ist die Integration mit Django's Authentifizierung - die Dokumentation kann automatisch die verfügbaren Authentifizierungsmethoden anzeigen.
Authentifizierung & Sicherheit in der Praxis
Die Sicherheit von APIs ist entscheidend für den Schutz sensibler Daten. Lassen Sie uns die Authentifizierungsmöglichkeiten in beiden Frameworks vergleichen.
Token-Authentifizierung
FastAPI mit JWT:
from fastapi import Depends, FastAPI, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from jose import JWTError, jwt
from passlib.context import CryptContext
app = FastAPI()
# Konfiguration
SECRET_KEY = "dein_geheimes_token"
ALGORITHM = "HS256"
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends()):
# Hier würde die Benutzerüberprüfung stehen
user_dict = {"username": form_data.username}
access_token = jwt.encode(user_dict, SECRET_KEY, algorithm=ALGORITHM)
return {"access_token": access_token, "token_type": "bearer"}
Django Ninja mit JWT:
from ninja.security import HttpBearer
from ninja import NinjaAPI
import jwt
class AuthBearer(HttpBearer):
def authenticate(self, request, token):
try:
return jwt.decode(token, "dein_geheimes_token", algorithms=["HS256"])
except:
return None
api = NinjaAPI(auth=AuthBearer())
@api.post("/token")
def login(request, username: str, password: str):
# Benutzerüberprüfung hier
return {"token": jwt.encode({"username": username}, "dein_geheimes_token")}
Berechtigungen (Permissions)
FastAPI:
from fastapi import Depends, HTTPException, status
def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
return username
except JWTError:
raise credentials_exception
@app.get("/secure/")
async def read_secure(current_user: str = Depends(get_current_user)):
return {"message": f"Hallo {current_user}"}
Django Ninja:
from ninja.security import django_auth
from django.contrib.auth.models import User
@api.get("/secure/", auth=django_auth)
def secure_route(request):
return f"Hallo {request.user.username}"
Sicherheits-Middleware
FastAPI Sicherheits-Header:
from fastapi import FastAPI
from fastapi.middleware.httpsredirect import HTTPSRedirectMiddleware
from fastapi.middleware.trustedhost import TrustedHostMiddleware
app = FastAPI()
# Erzwinge HTTPS
app.add_middleware(HTTPSRedirectMiddleware)
# Erlaube nur bestimmte Hosts
app.add_middleware(
TrustedHostMiddleware,
allowed_hosts=["example.com", "*.example.com"],
)
Django Ninja (erbt von Django):
# settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
# ...
]
# Sicherheitseinstellungen
SECURE_HSTS_SECONDS = 31536000 # 1 Jahr
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_SSL_REDIRECT = True
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
Zusammenfassung der Sicherheitsfeatures
- FastAPI: Bietet maximale Flexibilität, erfordert aber manuelle Konfiguration vieler Sicherheitsaspekte. Ideal für Entwickler, die volle Kontrolle benötigen.
- Django Ninja: Nutzt Djangos bewährte Sicherheitsfeatures wie CSRF-Schutz, Clickjacking-Schutz und sichere Cookies. Bietet eine höhere Sicherheit durch Voreinstellungen, ist aber weniger flexibel in der Anpassung.
Projektstruktur und Deployment
Eine klare Projektstruktur und ein reibungsloses Deployment sind entscheidend für den Erfolg Ihrer API. Hier sind die Best Practices für beide Frameworks.
Projektstruktur
FastAPI empfohlene Struktur:
fastapi_project/
├── app/
│ ├── __init__.py
│ ├── main.py # Hauptanwendung
│ ├── config.py # Konfiguration
│ ├── database.py # Datenbankverbindung
│ ├── models/ # Pydantic Modelle
│ │ └── schemas.py
│ ├── api/ # API-Endpunkte
│ │ ├── __init__.py
│ │ ├── v1/ # API Version 1
│ │ │ ├── __init__.py
│ │ │ ├── endpoints/ # Endpunkt-Module
│ │ │ └── deps.py # Abhängigkeiten
│ ├── core/ # Kernlogik
│ └── tests/ # Tests
├── alembic/ # Datenbank-Migrationen
├── static/ # Statische Dateien
├── requirements.txt
└── .env # Umgebungsvariablen
Django Ninja empfohlene Struktur:
django_project/
├── manage.py
├── requirements.txt
├── .env
├── config/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── asgi.py
├── apps/
│ ├── __init__.py
│ └── api/
│ ├── __init__.py
│ ├── schemas.py # Pydantic-Schemas
│ ├── routers.py # API-Router
│ └── tests/
└── static/
Deployment mit Docker
FastAPI Dockerfile:
# Basis-Image mit Python 3.9
FROM python:3.9-slim
# Arbeitsverzeichnis setzen
WORKDIR /app
# Abhängigkeiten installieren
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Anwendung kopieren
COPY . .
# Port freigeben
EXPOSE 8000
# Startbefehl
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Docker Compose für FastAPI:
version: '3.8'
services:
web:
build: .
ports:
- "8000:8000"
env_file: .env
depends_on:
- db
restart: unless-stopped
db:
image: postgres:13
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_NAME}
volumes:
- postgres_data:/var/lib/postgresql/data/
ports:
- "5432:5432"
volumes:
postgres_data:
Django Ninja Dockerfile:
# Basis-Image mit Python 3.9
FROM python:3.9-slim
# Arbeitsverzeichnis setzen
WORKDIR /app
# System-Abhängigkeiten installieren
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
# Python-Abhängigkeiten installieren
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Anwendung kopieren
COPY . .
# Statische Dateien sammeln
RUN python manage.py collectstatic --noinput
# Port freigeben
EXPOSE 8000
# Startbefehl
CMD ["gunicorn", "config.wsgi:application", "--bind", "0.0.0.0:8000"]
Deployment-Optionen
FastAPI:
- Uvicorn/ASGI-Server: Für Produktionseinsatz hinter einem Reverse-Proxy
- Gunicorn mit Uvicorn Workern: Für bessere Auslastung
- Cloud-Anbieter: AWS (ECS, EKS), Google Cloud Run, Azure App Service
- Serverless: AWS Lambda mit Mangum
Django Ninja:
- Gunicorn/Uvicorn: Für synchrone/asynchrone Endpunkte
- Daphne: ASGI-Server für volle asynchrone Unterstützung
- Cloud-Anbieter: Wie FastAPI, plus spezielle Django-Hosting-Anbieter
- PaaS: Heroku, PythonAnywhere, Railway
CI/CD Integration
Beide Frameworks können problemlos in CI/CD-Pipelines integriert werden. Hier ein Beispiel für GitHub Actions:
name: Django CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:13
env:
POSTGRES_USER: test
POSTGRES_PASSWORD: test
POSTGRES_DB: test
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.9'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run tests
env:
DATABASE_URL: postgresql://test:test@localhost:5432/test
run: |
python manage.py test
Praktische Pro-Tipps
1. HTTP-Status-Codes richtig nutzen
Problem: Django Ninja hat standardmäßig keine integrierte HTTP-Status-Code-Enumeration.
Lösung: Erstelle eine wiederverwendbare http_status.py
Datei:
# http_status.py
from http import HTTPStatus
from typing import Any, Dict, Optional
from ninja import Response
def json_response(
data: Any = None,
status: int = HTTPStatus.OK,
headers: Optional[Dict[str, str]] = None,
) -> Response:
"""Erstellt eine JSON-Response mit korrektem Status-Code."""
return Response(
content=data,
status=status.value,
headers=headers or {},
content_type="application/json",
)
# Verwendung:
# return json_response({"message": "Erfolg!"}, status=HTTPStatus.CREATED)
2. Performance-Optimierung für Django Ninja
# 1. Verwende select_related und prefetch_related
@api.get("/users/{user_id}")
def get_user(request, user_id: int):
user = get_object_or_404(User.objects.select_related('profile'), id=user_id)
return {"name": user.name, "email": user.email}
# 2. Paginierung für bessere Performance
from ninja.pagination import paginate, PageNumberPagination
@api.get("/articles/", response=List[ArticleSchema])
@paginate(PageNumberPagination, page_size=20)
def list_articles(request):
return Article.objects.all()
3. FastAPI Performance-Tuning
# 1. Verwende Pydantic's orm_mode für bessere Performance
class UserResponse(BaseModel):
id: int
username: str
email: str
class Config:
orm_mode = True
# 2. Caching für häufig abgerufene Endpunkte
from fastapi_cache import FastAPICache
from fastapi_cache.backends.redis import RedisBackend
from fastapi_cache.decorator import cache
@router.get("/expensive-query/")
@cache(expire=300) # Cache für 5 Minuten
async def expensive_query():
# Langsame Abfrage hier
return {"result": "Daten aus dem Cache oder berechnet"}
4. Fehlerbehandlung
Django Ninja:
from ninja import NinjaAPI
from ninja.errors import HttpError
api = NinjaAPI()
@api.exception_handler(ValueError)
def handle_validation_error(request, exc):
return api.create_response(
request,
{"detail": str(exc)},
status=400,
)
FastAPI:
from fastapi import FastAPI, HTTPException, Request
from fastapi.responses import JSONResponse
app = FastAPI()
@app.exception_handler(ValueError)
async def validation_exception_handler(request: Request, exc: ValueError):
return JSONResponse(
status_code=400,
content={"detail": str(exc)},
)
5. Dokumentation verbessern
FastAPI:
@app.get(
"/items/{item_id}",
response_model=Item,
summary="Hole ein Item",
description="""
Diese Route gibt ein einzelnes Item zurück.
- **item_id**: Die eindeutige ID des Items
""",
responses={
200: {"model": Item, "description": "Das angeforderte Item"},
404: {"description": "Item nicht gefunden"},
},
)
async def read_item(item_id: int):
return {"id": item_id, "name": "Beispiel"}
Django Ninja:
@api.get(
"/items/{item_id}",
response=ItemSchema,
summary="Hole ein Item",
description="""
Diese Route gibt ein einzelnes Item zurück.
- **item_id**: Die eindeutige ID des Items
""",
tags=["Items"],
operation_id="get_item",
)
def get_item(request, item_id: int):
return {"id": item_id, "name": "Beispiel"}
6. Umgebungsvariablen verwalten
Erstelle eine config.py
für beide Frameworks:
# config.py
import os
from pydantic import BaseSettings, PostgresDsn
class Settings(BaseSettings):
# Datenbank
DATABASE_URL: str = "postgresql://user:password@localhost/dbname"
# Sicherheit
SECRET_KEY: str = "your-secret-key"
ALGORITHM: str = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
class Config:
env_file = ".env"
case_sensitive = True
settings = Settings()
7. Logging einrichten
Für beide Frameworks:
import logging
from pathlib import Path
# Logger konfigurieren
log_dir = Path("logs")
log_dir.mkdir(exist_ok=True)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
handlers=[
logging.FileHandler(log_dir / "api.log"),
logging.StreamHandler(),
],
)
logger = logging.getLogger(__name__)
# Verwendung:
# logger.info("API gestartet")
# logger.error("Ein Fehler ist aufgetreten", exc_info=True)
Fazit: Wann solltest du welches Framework wählen?
Nach diesem tiefen Einblick fragst du dich sicher: "Welches Framework ist das richtige für mich?" Die Antwort hängt von deinen Anforderungen ab.
Wähle FastAPI wenn:
- Du eine neue API von Grund auf entwickelst
- Maximale Performance und async-Support kritisch sind
- Du volle Kontrolle über jeden Aspekt deiner Anwendung willst
- Dein Team bereits Erfahrung mit modernen Python-Patterns hat
- Du primär APIs entwickelst (keine traditionellen Web-Views)
Wähle Django Ninja wenn:
- Du bereits ein Django-Projekt hast oder planst
- Du Django's Utilities (ORM, Admin, Auth, etc.) nutzen möchtest
- Dein Team Django-Erfahrung hat
- Du eine Mischung aus API und traditionellen Django-Views brauchst
- Schnelle Entwicklung wichtiger ist als maximale Performance
Beide Frameworks sind hervorragend und die Entscheidung ist keine Entweder-Oder-Frage. In der Praxis kannst du sogar beide in verschiedenen Projekten oder Microservices einsetzen. Das Wichtigste ist, dass du die Stärken und Schwächen verstehst und das richtige Werkzeug für deine spezifische Aufgabe wählst.
Die Entscheidung zwischen FastAPI und Django Ninja ist keine reine Technologiefrage – es geht darum, das richtige Werkzeug für deine spezifischen Anforderungen zu finden. Beide Frameworks ermöglichen es dir, moderne, performante APIs zu entwickeln, die den höchsten Standards entsprechen. Die Kunst liegt darin, die Stärken des gewählten Frameworks optimal zu nutzen und eine Architektur zu entwickeln, die nicht nur heute funktioniert, sondern auch morgen noch erweiterbar ist.
Stehst du vor der Entscheidung, welches Framework für dein nächstes Projekt das richtige ist? Oder planst du eine Migration deiner bestehenden API? Bei Blueshoe haben umfangreiche Erfahrung mit beiden Frameworks und unterstützen dich gerne dabei, die optimale Lösung für deine Anforderungen zu finden. Von der Architekturberatung über die Implementierung bis hin zur Performance-Optimierung – lass uns gemeinsam deine API-Vision Wirklichkeit werden lassen. Kontaktiere uns für ein unverbindliches Beratungsgespräch und profitiere von unserer Expertise in der modernen Python-Webentwicklung!
Häufig gestellte Fragen (FAQs)
1. Kann ich von FastAPI zu Django Ninja (oder umgekehrt) migrieren?
Die Migration ist definitiv möglich, aber der Aufwand hängt stark von deiner Codebasis ab. Von FastAPI zu Django Ninja ist oft einfacher, da du "nur" ein Django-Projekt drumherum bauen musst. Die API-Syntax ist so ähnlich, dass viele Endpoints mit minimalen Anpassungen übernommen werden können. Der größte Aufwand entsteht bei der Migration der Datenbank-Layer - von SQLAlchemy zu Django ORM.
Die umgekehrte Richtung (Django Ninja zu FastAPI) erfordert mehr Arbeit, da du die gesamte Django-Infrastruktur ersetzen musst. Du musst Authentifizierung, Datenbankzugriff, Middleware und andere Django-Features neu implementieren. Mein Tipp: Plane eine schrittweise Migration über mehrere Sprints und nutze die Übergangszeit, um beide APIs parallel zu betreiben.
2. Welches Framework ist schneller in der Performance?
FastAPI hat in reinen Benchmarks meist die Nase vorn, besonders bei asynchronen Operationen. Die Zahlen können beeindruckend sein - FastAPI kann teilweise doppelt so viele Requests pro Sekunde verarbeiten. Aber Vorsicht: Diese synthetischen Benchmarks spiegeln selten die Realität wider!
In der Praxis ist der Flaschenhals fast nie das Web-Framework selbst, sondern Datenbankzugriffe, externe API-Calls oder komplexe Business-Logik. Django Ninja's Performance ist für die allermeisten Anwendungen mehr als ausreichend. Wenn du wirklich jede Millisekunde brauchst, ist FastAPI mit async/await die bessere Wahl. Aber bedenke: Premature optimization is the root of all evil. Optimiere erst, wenn du echte Performance-Probleme identifiziert hast.
3. Wie sieht es mit Testing aus?
Beide Frameworks bieten exzellente Testing-Unterstützung, aber mit unterschiedlichen Ansätzen.
Bei FastAPI nutzt du typischerweise TestClient von Starlette:
from fastapi.testclient import TestClient
client = TestClient(app)
response = client.get("/items/1")
assert response.status_code == 200
Django Ninja profitiert vom ausgereiften Django-Test-Framework mit all seinen Features wie Fixtures, Transactional Tests und der Test-Datenbank. Du kannst sowohl Django's TestCase als auch Ninja's eigenen Test-Client verwenden. Der große Vorteil: Du kannst deine API-Tests nahtlos mit anderen Django-Tests kombinieren und hast Zugriff auf Dinge wie Factory Boy oder Model Mommy für Test-Daten.
4. Kann ich beide Frameworks im selben Projekt verwenden?
Technisch gesehen ja, aber ich rate davon ab! Du könntest theoretisch FastAPI für hochperformante Endpoints und Django (mit Ninja) für den Rest verwenden. In der Praxis führt das aber zu unnötiger Komplexität: zwei verschiedene Routing-Systeme, zwei Arten von Middlewares, potenzielle Konflikte bei Dependencies.
Eine bessere Strategie wäre eine Microservice-Architektur, wo verschiedene Services unterschiedliche Frameworks nutzen. Zum Beispiel: Django Ninja für deine Haupt-API mit Nutzerverwaltung und Business-Logik, FastAPI für einen spezialisierten Service, der Echtzeit-Datenverarbeitung macht.
5. Welches Framework hat die steilere Lernkurve?
Das hängt stark von deinem Hintergrund ab! Wenn du bereits Django kennst, wirst du dich bei Django Ninja sofort zuhause fühlen. Die API-Syntax ist intuitiv und du kannst dein Django-Wissen direkt anwenden.
FastAPI hat initial eine flachere Lernkurve, wenn du bei null startest. Die Konzepte sind modern und klar strukturiert. Aber sobald du über "Hello World" hinausgehst, musst du viele Entscheidungen treffen und Dinge selbst implementieren. Das kann überwältigend sein, wenn du nicht genau weißt, was du brauchst.
Mein Rat: Wenn du Python-Webentwicklung lernen willst, starte mit FastAPI für das Verständnis moderner API-Konzepte. Wenn du produktiv werden willst und bereits etwas Erfahrung hast, könnte Django Ninja der schnellere Weg sein.
6. Wie steht es um die Zukunftssicherheit beider Frameworks?
FastAPI hat enormen Momentum gewonnen und wird von einer sehr aktiven Community unterstützt. Große Unternehmen wie Microsoft, Netflix und Uber setzen es ein. Die Entwicklung ist sehr aktiv und das Framework wird ständig verbessert.
Django Ninja ist jünger und hat eine kleinere Community, profitiert aber von der Stabilität des Django-Ökosystems. Solange Django relevant bleibt (und dafür spricht alles), wird auch Django Ninja eine solide Wahl sein. Der Vorteil: Selbst wenn Django Ninja die Entwicklung einstellen würde, könntest du relativ einfach auf Django REST Framework oder pure Django-Views migrieren.
7. Gibt es Situationen, wo keines der beiden Frameworks passt?
Absolut! Wenn du eine GraphQL-API bauen willst, schau dir Strawberry oder Graphene an. Für WebSocket-heavy Anwendungen könnte Starlette oder Django Channels besser passen.
Für sehr einfache APIs oder Prototypen könnte auch Flask mit Flask-RESTX ausreichen. Und wenn du in der Data Science Welt unterwegs bist, könnte Streamlit oder Gradio für API-ähnliche Interfaces interessant sein. Das Schöne am Python-Ökosystem ist die Vielfalt - es gibt für jeden Use Case das passende Tool!
Hast du noch Fragen oder eine Meinung? Mit deinem GitHub Account kannst Du es uns wissen lassen...
Was unsere Kunden über uns sagen
- Ofa Bamberg GmbHB2B Online-Shop | B2C Website | Hosting | Betreuung | Security© Ofa Bamberg GmbH
- Ludwig-Maximilians-Universität MünchenPlattformentwicklung | Hosting | Betreuung | APIs | Website
Blueshoe hat unsere Forschungsdatenplattform Munich Media Monitoring (M3) entwickelt und uns hervorragend dabei beraten. Das Team hat unsere Anforderungen genau verstanden und sich aktiv in die Ausgestaltung der Software und der Betriebsumgebung eingebracht. Wir sind froh, dass auch Wartung und weiterführender Support in Blueshoes Händen liegen.
- Deutsches MuseumDigitalisierung | Beratung | Datenbank-Optimierung | GraphQL | CMSFoto: Anne Göttlicher
Im Rahmen eines komplexen Digitalisierungsprojekts für unsere Exponate-Datenbank war Blueshoe ein äußerst verlässlicher Partner. Sie haben uns nicht nur während des gesamten Projekts hervorragend beraten, sondern unsere Anforderungen perfekt umgesetzt. Dank ihrer Arbeit ist unsere Datenbank nun ein bedeutender Mehrwert für die weltweite wissenschaftliche Forschung.
- Fonds Finanz Maklerservice GmbHPlattformentwicklung | Prozess-Systeme | Hosting | Betreuung | Zertifikate | Website© Fonds Finanz Maklerservice GmbH
Blueshoe ist unsere verlängerte Werkbank für Entwicklung, Wartung und Support unserer Weiterbildungs- und Zertifizierungsplattformen. Das Team hat sich gründlich in unsere Abläufe eingearbeitet, und wir freuen uns, Blueshoe als zuverlässigen Partner an unserer Seite zu haben.
- Technische Universität HamburgPlattformentwicklung | Beratung | Prozess-Systeme | Hosting | Website
Seit 2019 unterstützt uns die Blueshoe GmbH tatkräftig bei der Entwicklung und Weiterentwicklung des "Digital Learning Lab" und der "Digital Learning Tools". Dank ihrer Beratung konnten wir von Anfang an auf eine zukunftssichere, moderne technische Struktur setzen. Die Zusammenarbeit ist reibungslos, und wir fühlen uns rundum gut betreut. Und davon profitieren dann auch die Lehrkräfte in Hamburg.