init at work
This commit is contained in:
Executable
+499
@@ -0,0 +1,499 @@
|
||||
Im Folgenden bekommst du eine umfassende, aber einsteigerfreundliche Einführung in FastAPI.
|
||||
|
||||
---
|
||||
|
||||
## 1. Grundidee: Was ist FastAPI?
|
||||
|
||||
**FastAPI** ist ein modernes, schnelles Web-Framework für Python, mit dem du **Web-APIs** (Schnittstellen) bauen kannst.
|
||||
Eine API ist eine „Schnittstelle“, über die andere Programme mit deinem Programm sprechen können – z. B. eine Web-App, ein Mobile-App-Backend oder interne Services in einem Unternehmen.
|
||||
|
||||
Kernpunkte von FastAPI:
|
||||
|
||||
- **Schwerpunkt:** Aufbau von **HTTP-APIs** (REST-APIs, JSON-basierte APIs).
|
||||
- **Geschwindigkeit:** Sehr performant durch Nutzung von **asynchronem Python** (`async`/`await`), basierend auf **ASGI**.
|
||||
- **Typisierung:** Starke Nutzung von **Python-Typannotationen** (z. B. `str`, `int`, eigene Klassen).
|
||||
→ Daraus entstehen automatisch:
|
||||
- Validierung von Daten,
|
||||
- automatische Dokumentation (Swagger / OpenAPI),
|
||||
- bessere IDE-Unterstützung (Autovervollständigung, Fehlererkennung).
|
||||
- **Auto-Dokumentation:** FastAPI generiert automatisch eine **interaktive API-Dokumentation** im Browser.
|
||||
|
||||
Ein typisches „Hello World“ mit FastAPI sieht so aus:
|
||||
|
||||
```python
|
||||
from fastapi import FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@app.get("/")
|
||||
def read_root():
|
||||
return {"message": "Hello World"}
|
||||
```
|
||||
|
||||
Starten kannst du das z. B. mit:
|
||||
|
||||
```bash
|
||||
uvicorn main:app --reload
|
||||
```
|
||||
|
||||
Dann ist die API z. B. unter `http://127.0.0.1:8000` erreichbar.
|
||||
|
||||
---
|
||||
|
||||
## 2. Abgrenzung: FastAPI vs. verwandte Begriffe und Frameworks
|
||||
|
||||
### 2.1 FastAPI vs. „API“ / REST / HTTP allgemein
|
||||
|
||||
- **HTTP**: Das zugrunde liegende Protokoll, über das Browser oder andere Dienste kommunizieren.
|
||||
- **REST-API**: Eine Art, HTTP-APIs zu strukturieren (z. B. `GET /users`, `POST /orders`).
|
||||
- **FastAPI**: Ein **Framework**, das dir hilft, solche HTTP/REST-APIs in Python zu bauen.
|
||||
|
||||
FastAPI „spricht“ also HTTP, baut REST-APIs, ist aber selbst das **Werkzeug**, kein Protokoll.
|
||||
|
||||
---
|
||||
|
||||
### 2.2 FastAPI vs. Flask
|
||||
|
||||
**Flask** ist ein sehr bekanntes, minimalistisches Python-Webframework.
|
||||
|
||||
**Ähnlichkeiten:**
|
||||
|
||||
- Beide erlauben es, mit wenig Code HTTP-Endpunkte zu definieren.
|
||||
- Beide sind relativ leichtgewichtig und flexibel.
|
||||
|
||||
**Unterschiede:**
|
||||
|
||||
- **Asynchronität**:
|
||||
- Flask: traditionell synchron (WSGI), Async ist erst neuerdings und eingeschränkt verfügbar.
|
||||
- FastAPI: von Anfang an für **async** gebaut (ASGI).
|
||||
- **Typen & Validierung**:
|
||||
- Flask: Kein eingebautes System für automatische Validierung – du machst das selbst oder mit Erweiterungen.
|
||||
- FastAPI: Nutzt **[[Pydantic]]**-Modelle und Typannotationen → automatische Validierung.
|
||||
- **Dokumentation**:
|
||||
- Flask: Kein automatisches API-Dokumentations-UI.
|
||||
- FastAPI: Automatisch generierte OpenAPI/Swagger-UI unter `/docs` und `/redoc`.
|
||||
|
||||
Praxisbeispiel Vergleich:
|
||||
|
||||
**Flask:**
|
||||
|
||||
```python
|
||||
from flask import Flask, request, jsonify
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/items", methods=["POST"])
|
||||
def create_item():
|
||||
data = request.get_json()
|
||||
name = data.get("name")
|
||||
price = data.get("price")
|
||||
if not isinstance(name, str) or not isinstance(price, (int, float)):
|
||||
return jsonify({"error": "Invalid data"}), 400
|
||||
return jsonify({"name": name, "price": price})
|
||||
```
|
||||
|
||||
**FastAPI:**
|
||||
|
||||
```python
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
class Item(BaseModel):
|
||||
name: str
|
||||
price: float
|
||||
|
||||
@app.post("/items")
|
||||
def create_item(item: Item):
|
||||
# item ist schon validiert
|
||||
return item
|
||||
```
|
||||
|
||||
FastAPI übernimmt hier die Validierung automatisch.
|
||||
|
||||
---
|
||||
|
||||
### 2.3 FastAPI vs. Django (und Django REST Framework)
|
||||
|
||||
**Django** ist ein „Full-Stack“-Framework:
|
||||
|
||||
- liefert Templates, ORM (Datenbankzugriff), Admin-Interface, Auth-System, Formulare etc.
|
||||
- ideal für klassische Webanwendungen mit HTML-Seiten.
|
||||
|
||||
Für APIs nutzt man meist **Django REST Framework (DRF)** als Erweiterung.
|
||||
|
||||
**FastAPI** dagegen ist:
|
||||
|
||||
- stärker auf **APIs** fokussiert,
|
||||
- nicht „alles aus einer Hand“, sondern:
|
||||
- Web-Layer: `Starlette`,
|
||||
- Datenvalidierung: `Pydantic`,
|
||||
- Datenbank: du wählst selbst z. B. SQLAlchemy, Tortoise ORM etc.
|
||||
|
||||
Faustregel:
|
||||
|
||||
- Wenn du eine klassische Website mit HTML-Rendering brauchst → Django.
|
||||
- Wenn du primär eine performant API bauen willst (z. B. für SPA, Microservices) → FastAPI ist sehr attraktiv.
|
||||
|
||||
---
|
||||
|
||||
### 2.4 FastAPI vs. Node.js / Express
|
||||
|
||||
**Node.js + Express** ist eine sehr verbreitete Lösung für APIs in JavaScript/TypeScript.
|
||||
|
||||
- **Sprache:** Node → JavaScript/TypeScript, FastAPI → Python.
|
||||
- **Typen:** TypeScript kann Typen bieten, FastAPI nutzt Python-Typen + [[Pydantic]].
|
||||
- **Ökosystem:** Node sehr stark im Web-/Frontend-nahen Bereich, Python stark bei Data Science, Machine Learning und Backend-Services.
|
||||
|
||||
FastAPI ist besonders interessant, wenn du sowieso Python nutzt (z. B. wegen ML/AI) und dafür eine passende Web-API brauchst.
|
||||
|
||||
---
|
||||
|
||||
## 3. Welche Probleme löst FastAPI?
|
||||
|
||||
### 3.1 Saubere, valide Eingabedaten
|
||||
|
||||
Problem ohne Framework-Unterstützung:
|
||||
|
||||
- Du bekommst z. B. einen JSON-Body und musst:
|
||||
- alle Felder prüfen (Typ, Pflichtfelder, Wertebereiche),
|
||||
- Fehler verständlich zurückgeben,
|
||||
- alles manuell machen.
|
||||
|
||||
FastAPI + [[Pydantic]] lösen das:
|
||||
|
||||
```python
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
class User(BaseModel):
|
||||
name: str = Field(..., min_length=3)
|
||||
age: int = Field(..., ge=0, le=120) # 0 <= age <= 120
|
||||
|
||||
@app.post("/users")
|
||||
def create_user(user: User):
|
||||
# Wenn name zu kurz oder age negativ ist, liefert FastAPI automatisch 422 mit Fehlerdetails
|
||||
return {"message": "User created", "user": user}
|
||||
```
|
||||
|
||||
Vorteil:
|
||||
|
||||
- Weniger Fehleranfälligkeit.
|
||||
- Konsistente Fehlerantworten.
|
||||
- Gute Developer-Erfahrung.
|
||||
|
||||
---
|
||||
|
||||
### 3.2 Automatische Dokumentation und Testbarkeit
|
||||
|
||||
FastAPI erzeugt automatisch eine OpenAPI-Spezifikation und UI:
|
||||
|
||||
- `http://localhost:8000/docs` → Swagger UI (interaktive Oberfläche, du kannst Requests direkt aus dem Browser abschicken).
|
||||
- `http://localhost:8000/redoc` → ReDoc, alternative Dokumentationsansicht.
|
||||
|
||||
Das hilft:
|
||||
|
||||
- Dir selbst beim Testen.
|
||||
- Frontend-Entwicklern oder anderen Teams, die deine API nutzen.
|
||||
- Beim automatisierten Generieren von Client-SDKs (z. B. TypeScript-Client).
|
||||
|
||||
---
|
||||
|
||||
### 3.3 Performance und asynchrones I/O
|
||||
|
||||
Problem:
|
||||
|
||||
- In „klassischen“ synchronen Webframeworks blockiert jeder Request, der z. B. auf eine externe API oder langsame DB wartet.
|
||||
- Bei vielen gleichzeitigen Anfragen leiden Durchsatz und Antwortzeit.
|
||||
|
||||
FastAPI setzt auf **ASGI** (Asynchronous Server Gateway Interface) und `async def`:
|
||||
|
||||
```python
|
||||
from fastapi import FastAPI
|
||||
import httpx # asynchroner HTTP-Client
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
@app.get("/external")
|
||||
async def call_external_api():
|
||||
async with httpx.AsyncClient() as client:
|
||||
response = await client.get("https://httpbin.org/get")
|
||||
return response.json()
|
||||
```
|
||||
|
||||
Vorteil:
|
||||
|
||||
- Viele I/O-lastige Requests können parallel abgewickelt werden.
|
||||
- Besonders sinnvoll bei Microservices, die viel mit anderen Services kommunizieren.
|
||||
|
||||
---
|
||||
|
||||
### 3.4 Abhängigkeiten und Wiederverwendbarkeit (Dependency Injection)
|
||||
|
||||
FastAPI bietet ein eingebautes **Dependency Injection**-System.
|
||||
Beim Entwickeln von APIs brauchst du häufig:
|
||||
|
||||
- Datenbankverbindungen,
|
||||
- Authentifizierungslogik,
|
||||
- Konfigurationsobjekte.
|
||||
|
||||
Ohne System würdest du das überall wiederholen oder global speichern.
|
||||
Mit FastAPI:
|
||||
|
||||
```python
|
||||
from fastapi import Depends, FastAPI
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
def get_settings():
|
||||
# z. B. Konfiguration laden
|
||||
return {"app_name": "Meine App"}
|
||||
|
||||
@app.get("/info")
|
||||
def read_info(settings = Depends(get_settings)):
|
||||
return {"app_name": settings["app_name"]}
|
||||
```
|
||||
|
||||
Das verbessert:
|
||||
|
||||
- Testbarkeit (du kannst Dependencies im Test austauschen),
|
||||
- Struktur deines Codes (klarere Trennung von Zuständigkeiten).
|
||||
|
||||
---
|
||||
|
||||
## 4. Typische Einsatzszenarien (praxisnah)
|
||||
|
||||
### Beispiel 1: Einfaches CRUD für ein „Item“
|
||||
|
||||
```python
|
||||
from fastapi import FastAPI, HTTPException
|
||||
from pydantic import BaseModel
|
||||
from typing import List
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
class Item(BaseModel):
|
||||
id: int
|
||||
name: str
|
||||
price: float
|
||||
|
||||
# „Fake-Datenbank“ im Speicher
|
||||
items_db: List[Item] = []
|
||||
|
||||
@app.post("/items", response_model=Item)
|
||||
def create_item(item: Item):
|
||||
# einfache Prüfung: ID darf nicht doppelt sein
|
||||
if any(existing.id == item.id for existing in items_db):
|
||||
raise HTTPException(status_code=400, detail="Item ID already exists")
|
||||
items_db.append(item)
|
||||
return item
|
||||
|
||||
@app.get("/items", response_model=List[Item])
|
||||
def list_items():
|
||||
return items_db
|
||||
|
||||
@app.get("/items/{item_id}", response_model=Item)
|
||||
def get_item(item_id: int):
|
||||
for item in items_db:
|
||||
if item.id == item_id:
|
||||
return item
|
||||
raise HTTPException(status_code=404, detail="Item not found")
|
||||
```
|
||||
|
||||
Du bekommst:
|
||||
|
||||
- JSON-APIs für CRUD,
|
||||
- automatische Dokumentation,
|
||||
- automatische Validierung für `Item`.
|
||||
|
||||
---
|
||||
|
||||
### Beispiel 2: Path-Parameter, Query-Parameter, Body
|
||||
|
||||
```python
|
||||
from fastapi import FastAPI
|
||||
from pydantic import BaseModel
|
||||
from typing import Optional
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
class SearchFilters(BaseModel):
|
||||
min_price: Optional[float] = None
|
||||
max_price: Optional[float] = None
|
||||
|
||||
@app.get("/products/{category}")
|
||||
def search_products(
|
||||
category: str,
|
||||
q: Optional[str] = None, # Query-Parameter ?q=Text
|
||||
filters: SearchFilters = None # Body JSON
|
||||
):
|
||||
return {
|
||||
"category": category,
|
||||
"query": q,
|
||||
"filters": filters
|
||||
}
|
||||
```
|
||||
|
||||
Beispiel-Request:
|
||||
|
||||
- `GET /products/books?q=python` mit JSON-Body:
|
||||
```json
|
||||
{
|
||||
"min_price": 10,
|
||||
"max_price": 50
|
||||
}
|
||||
```
|
||||
|
||||
FastAPI erkennt:
|
||||
|
||||
- `category` als Pfadparameter,
|
||||
- `q` als Query-Parameter,
|
||||
- `filters` als JSON-Body und validiert ihn.
|
||||
|
||||
---
|
||||
|
||||
### Beispiel 3: Einfache Authentifizierung per Token
|
||||
|
||||
```python
|
||||
from fastapi import Depends, FastAPI, HTTPException, Header
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
def get_current_user(x_token: str = Header(...)):
|
||||
if x_token != "secrettoken123":
|
||||
raise HTTPException(status_code=401, detail="Invalid or missing token")
|
||||
return {"username": "alice"}
|
||||
|
||||
@app.get("/profile")
|
||||
def read_profile(current_user = Depends(get_current_user)):
|
||||
return {"message": f"Hello, {current_user['username']}"}
|
||||
```
|
||||
|
||||
Hier:
|
||||
|
||||
- Der Endpunkt `/profile` verlangt einen HTTP-Header `X-Token`.
|
||||
- FastAPI übernimmt das Zusammenspiel von Header → Dependency → Endpoint-Logik.
|
||||
|
||||
---
|
||||
|
||||
## 5. Herausforderungen und typische Stolpersteine
|
||||
|
||||
FastAPI nimmt dir viel ab, aber es gibt einige Themen, die für Einsteiger Hürden sein können:
|
||||
|
||||
### 5.1 Asynchrones Programmieren (`async` / `await`)
|
||||
|
||||
- Wenn du noch nie mit Async gearbeitet hast, ist es ungewohnt:
|
||||
- Wann nutze ich `async def`?
|
||||
- Wo brauche ich `await`?
|
||||
- Was ist „Blocking I/O“?
|
||||
- Du musst darauf achten, dass du **asynchrone Bibliotheken** verwendest, wenn du im Handler `async` einsetzt
|
||||
(z. B. `httpx` statt `requests`, `asyncpg` statt `psycopg2`).
|
||||
|
||||
Wenn du erst mal einsteigst, kannst du auch erst **synchron** (ohne `async`) starten und später umstellen.
|
||||
|
||||
---
|
||||
|
||||
### 5.2 Typannotationen und Pydantic verstehen
|
||||
|
||||
FastAPI baut stark auf Typen auf:
|
||||
|
||||
- Für jemanden ohne Erfahrung mit Typannotationen in Python ist das anfangs ungewohnt.
|
||||
- Du musst verstehen:
|
||||
- Wie du eigene Modelle mit `BaseModel` definierst.
|
||||
- Wie optionale Felder mit `Optional[...]` und Standardwerten funktionieren.
|
||||
- Wie Validierung und Fehlernachrichten von [[Pydantic]] aussehen.
|
||||
|
||||
Aber:
|
||||
Der Lerneffekt lohnt sich, weil du insgesamt saubereren, stabileren Code bekommst.
|
||||
|
||||
---
|
||||
|
||||
### 5.3 Datenbankintegration
|
||||
|
||||
FastAPI selbst bringt keinen [[ORM]] mit. Du musst wählen:
|
||||
|
||||
- z. B. **[[SQLAlchemy]]**, Tortoise-ORM, Prisma, Gino etc.
|
||||
|
||||
Dabei stellen sich Fragen wie:
|
||||
|
||||
- Wie verwalte ich Datenbank-Sessions pro Request?
|
||||
- Nutze ich die sync- oder async-Variante meiner ORM?
|
||||
- Wie realisiere ich Migrations (alembic, etc.)?
|
||||
|
||||
Es gibt viele Beispielprojekte, aber es ist ein zusätzlicher Schritt im Vergleich zu Django, wo ein [[ORM]] „eingebaut“ ist.
|
||||
|
||||
---
|
||||
|
||||
### 5.4 Deployment / Betrieb
|
||||
|
||||
Für Einsteiger ist der Weg von „läuft lokal“ zu „läuft im Internet“ oft herausfordernd:
|
||||
|
||||
- FastAPI-Anwendung läuft typischerweise mit:
|
||||
- [[uvicorn]] oder [[hypercorn]] (ASGI-Server),
|
||||
- oft hinter einem Reverse Proxy wie [[Nginx]].
|
||||
- Themen:
|
||||
- Logging konfigurieren,
|
||||
- Umgebungsvariablen (Konfiguration),
|
||||
- HTTPS/SSL (z. B. via [[Nginx]]/Let’s Encrypt),
|
||||
- Skalierung (mehrere Worker, z. B. `gunicorn` + `uvicorn.workers.UvicornWorker`).
|
||||
|
||||
Für den Anfang kannst du auch auf Plattformen wie Render, Railway, fly.io, oder Docker + Cloud setzen.
|
||||
|
||||
---
|
||||
|
||||
### 5.5 Versionierung und Wartung großer Projekte
|
||||
|
||||
Bei größeren APIs:
|
||||
|
||||
- Wie strukturiere ich meinen Code?
|
||||
- z. B. mit **Routern** (`APIRouter`) und Modulen.
|
||||
- Wie versioniere ich die API? (`/v1/user`, `/v2/user`, …)
|
||||
- Wie halte ich die Dokumentation aktuell?
|
||||
- FastAPI hilft zwar, aber bei vielen Endpunkten braucht man Konventionen und ggf. zusätzliche Dokumentation.
|
||||
|
||||
Beispiel mit Router:
|
||||
|
||||
```python
|
||||
from fastapi import FastAPI, APIRouter
|
||||
|
||||
app = FastAPI()
|
||||
items_router = APIRouter(prefix="/items", tags=["items"])
|
||||
|
||||
@items_router.get("/")
|
||||
def list_items():
|
||||
return [{"id": 1, "name": "Item 1"}]
|
||||
|
||||
app.include_router(items_router)
|
||||
```
|
||||
|
||||
So kannst du größere Projekte modular strukturieren.
|
||||
|
||||
---
|
||||
|
||||
## 6. Zusammenfassung
|
||||
|
||||
- **FastAPI** ist ein modernes Framework für **Web-APIs in Python**, fokussiert auf:
|
||||
- hohe **Performance** (async),
|
||||
- **Typen** + automatische Validierung ([[Pydantic]]),
|
||||
- automatische **OpenAPI-/Swagger-Dokumentation**,
|
||||
- gute Developer Experience.
|
||||
|
||||
- Es unterscheidet sich von:
|
||||
- **Flask**: moderner, stärker typisiert, async-first, integrierte Validierung & Doku.
|
||||
- **Django**: kein Full-Stack-Framework, sondern eher API-fokussiert; du kombinierst es mit eigenen Tools für DB, Templates etc.
|
||||
- Node/Express: andere Sprache, andere Ökosysteme; FastAPI besonders stark, wenn du ohnehin Python nutzt.
|
||||
|
||||
- Es löst typische Probleme beim API-Bau:
|
||||
- Validierung von Eingaben,
|
||||
- Dokumentation & Testbarkeit,
|
||||
- Performance bei vielen gleichzeitigen Anfragen,
|
||||
- saubere Struktur durch Dependency Injection.
|
||||
|
||||
- Herausforderungen:
|
||||
- Einstieg in asynchrones Programmieren,
|
||||
- Verständnis von Typannotationen & [[Pydantic]],
|
||||
- separate Auswahl & Integration einer Datenbanklösung,
|
||||
- Deployment & Betrieb.
|
||||
Reference in New Issue
Block a user