FastAPI od nuly: Nastavení, tipy pro typy a vlastní dokumentace OpenAPI
Naučte se, jak spustit projekt FastAPI za méně než 5 minut: zadejte tipy jako smlouvu API, Pydantic v2 pro ověřování dat a automaticky generovanou dokumentaci Swagger bez dodatečné konfigurace.
Proč FastAPI v roce 2026
FastAPI se během několika let změnilo z experimentálního projektu na referenční rámec pro API Python ve výrobě. Podle průzkumu Python Developers Survey 2024 se jedná o druhý framework Python web podle difúze (38 %), překonán pouze Django. Důvody jsou konkrétní: výkon srovnatelné s Node.js a Go for I/O-bound workloads, zero-boilerplate data validation with Pydantic v2 a dokumentace OpenAPI automaticky generovaná z kódu.
Tajemství je architektonické: FastAPI je postaveno na Hvězdičky (rámec ASGI) e Pydantický (validace s jádrem Rust). Nepřidává zbytečné abstrakce – každý prvek má přesný technický důvod.
Co se naučíte
- Instalace a spuštění prvního FastAPI serveru za 5 minut
- Jak se tipy typu Python stávají ověřováním, serializací a dokumentací
- Parametry cesty, parametry dotazů a těla požadavků s Pydantic
- Uživatelské rozhraní Swagger a ReDoc: Procházení automaticky generované dokumentace
- Stavové kódy, modely odezvy a základní zpracování chyb
- Struktura skutečného projektu FastAPI (nejen jeden soubor)
Instalace a první server
FastAPI vyžaduje Python 3.8+, ale pro lepší výkon doporučujeme 3.11+ asyncio a nové funkce tipů typu. Uvicorn je server ASGI doporučeno pro místní rozvoj.
# Ambiente virtuale (sempre, mai installare globalmente)
python -m venv .venv
source .venv/bin/activate # Linux/Mac
# .venv\Scripts\activate # Windows
# Installazione dipendenze core
pip install fastapi uvicorn[standard]
# Per sviluppo aggiungere anche:
pip install httpx pytest pytest-asyncio
# Verifica installazione
python -c "import fastapi; print(fastapi.__version__)"
# 0.115.x
Minimální možný server. Uložit toto jako main.py:
# main.py - Il server FastAPI piu semplice possibile
from fastapi import FastAPI
# Crea l'istanza dell'applicazione
# title e description appaiono nella documentazione Swagger
app = FastAPI(
title="La Mia API",
description="API costruita con FastAPI e Python type hints",
version="1.0.0",
)
# Decorator che registra la route GET /
@app.get("/")
def read_root():
# Il dict viene automaticamente serializzato in JSON
return {"message": "Hello, FastAPI!", "status": "running"}
# Avvio con: uvicorn main:app --reload
# main = nome del file, app = variabile FastAPI, --reload = hot reload
# Avvia il server con hot reload (ricrea il server ad ogni modifica)
uvicorn main:app --reload
# Output:
# INFO: Will watch for changes in these directories: ['/path/to/project']
# INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
# INFO: Started reloader process [12345]
# INFO: Started server process [12346]
# INFO: Waiting for application startup.
# INFO: Application startup complete.
OTEVŘENO http://127.0.0.1:8000/docs zobrazit vygenerované uživatelské rozhraní Swagger
automaticky. Nic jste nenakonfigurovali: FastAPI načetlo anotace kódu
a vytvořil kompletní dokumentaci.
Zadejte Hints jako API kontrakt
Nejvýkonnější funkcí FastAPI je použití tipů typu Python jako např Definice smlouvy API. Každý anotovaný parametr se automaticky stane: ověřeno, zdokumentováno a serializováno. Nulový dodatečný standardní kód.
# routes/users.py - Esempi di parametri con type hints
from fastapi import FastAPI, Path, Query, HTTPException
from typing import Optional
from pydantic import BaseModel, EmailStr, Field
from datetime import datetime
app = FastAPI()
# --- PATH PARAMETERS ---
# Il tipo int fa si che FastAPI validi che userId sia un intero
@app.get("/users/{user_id}")
def get_user(
user_id: int, # Path parameter: automaticamente estratto dall'URL
):
if user_id <= 0:
raise HTTPException(status_code=400, detail="user_id must be positive")
return {"user_id": user_id, "name": f"User {user_id}"}
# Path con validazione avanzata tramite Path()
@app.get("/items/{item_id}")
def get_item(
item_id: int = Path(
title="The ID of the item",
description="Must be a positive integer",
ge=1, # greater than or equal to 1
le=1000, # less than or equal to 1000
),
):
return {"item_id": item_id}
# --- QUERY PARAMETERS ---
# Parametri con default = opzionali, senza default = obbligatori
@app.get("/search")
def search_users(
q: str, # Obbligatorio (no default)
page: int = 1, # Opzionale con default
limit: int = Query(default=10, ge=1, le=100), # Con validazione
active_only: bool = True, # Bool viene da "true"/"false" nella query string
role: Optional[str] = None, # Opzionale, None se non fornito
):
return {
"query": q,
"page": page,
"limit": limit,
"active_only": active_only,
"role": role,
}
# GET /search?q=mario&page=2&limit=20&active_only=false&role=admin
Vyžádejte si tělo s Pydantickými modely
Pro data v těle požadavku POST/PUT/PATCH se používají šablony Pydantic. FastAPI automaticky deserializuje příchozí JSON, ověří jej proti šabloně, a zpřístupní jej jako typovaný objekt Pythonu.
# models/user.py - Definizione dei modelli con Pydantic v2
from pydantic import BaseModel, EmailStr, Field, field_validator
from typing import Optional
from enum import Enum
class UserRole(str, Enum):
admin = "admin"
editor = "editor"
viewer = "viewer"
# Modello per la creazione di un utente (in input)
class UserCreate(BaseModel):
name: str = Field(
min_length=2,
max_length=100,
description="Full name of the user",
examples=["Mario Rossi"],
)
email: EmailStr # Validazione email inclusa in Pydantic
role: UserRole = UserRole.viewer # Default al valore meno privilegiato
age: Optional[int] = Field(default=None, ge=0, le=150)
# Validator personalizzato (Pydantic v2 syntax)
@field_validator("name")
@classmethod
def name_must_contain_space(cls, v: str) -> str:
if " " not in v:
raise ValueError("name must contain at least first and last name")
return v.strip()
# Modello per la risposta (include campi generati dal server)
class UserResponse(BaseModel):
id: int
name: str
email: EmailStr
role: UserRole
created_at: str # ISO 8601
# Route POST che usa i modelli
@app.post(
"/users",
response_model=UserResponse, # Definisce la struttura della risposta
status_code=201, # HTTP 201 Created
summary="Create a new user",
tags=["users"],
)
def create_user(user: UserCreate):
# user e gia validato e typed come UserCreate
# FastAPI ha deserializzato il JSON e verificato tutti i vincoli
new_user = {
"id": 42, # In realta verrebbe dal database
"name": user.name,
"email": user.email,
"role": user.role.value,
"created_at": "2026-06-01T10:00:00Z",
}
return new_user
# Solo i campi di UserResponse vengono inclusi nella risposta
# (response_model filtra automaticamente campi extra come password hash)
Zpracování chyb pomocí HTTPException
FastAPI mapuje výjimky do strukturovaných HTTP odpovědí. Používá standardní vzor
HTTPException pro očekávané chyby a obslužnou rutinu globálních výjimek
neočekávané chyby.
# Errori standard con HTTPException
from fastapi import HTTPException, status
@app.get("/users/{user_id}", response_model=UserResponse)
def get_user(user_id: int):
user = db.find_user(user_id) # Ipotetica funzione DB
if user is None:
# status.HTTP_404_NOT_FOUND = 404 (uso le costanti, piu leggibile)
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"User with id {user_id} not found",
)
return user
# Exception handler globale per errori non gestiti
from fastapi import Request
from fastapi.responses import JSONResponse
@app.exception_handler(Exception)
async def generic_exception_handler(request: Request, exc: Exception):
# Log l'errore (NON esporre il dettaglio in produzione)
import logging
logging.error(f"Unhandled exception: {exc}", exc_info=True)
return JSONResponse(
status_code=500,
content={"detail": "Internal server error"},
)
Struktura reálného projektu
Singl main.py je to dobré pro tutoriály, ale ne pro skutečný projekt.
Doporučená struktura rozděluje obavy do soudržných modulů:
# Struttura consigliata per un progetto FastAPI medio
my_api/
├── app/
│ ├── __init__.py
│ ├── main.py # Entry point: crea l'app FastAPI e include i router
│ ├── config.py # Configurazione (env vars, Settings con Pydantic)
│ ├── database.py # Connessione DB, session factory
│ ├── models/
│ │ ├── __init__.py
│ │ ├── user.py # SQLAlchemy ORM models
│ │ └── item.py
│ ├── schemas/ # Pydantic models (request/response)
│ │ ├── __init__.py
│ │ ├── user.py # UserCreate, UserUpdate, UserResponse
│ │ └── item.py
│ ├── routers/ # APIRouter per ogni dominio
│ │ ├── __init__.py
│ │ ├── users.py # /users endpoints
│ │ └── items.py # /items endpoints
│ ├── services/ # Business logic (separata dai router)
│ │ ├── user_service.py
│ │ └── item_service.py
│ └── dependencies.py # Depends() condivise (auth, DB session)
├── tests/
│ ├── conftest.py
│ ├── test_users.py
│ └── test_items.py
├── alembic/ # Migrations DB
├── pyproject.toml
└── docker-compose.yml
# app/main.py - Entry point con router modulari
from fastapi import FastAPI
from app.routers import users, items
from app.config import get_settings
settings = get_settings()
app = FastAPI(
title=settings.APP_NAME,
version=settings.APP_VERSION,
docs_url="/docs" if settings.DEBUG else None, # Disabilita docs in produzione
redoc_url="/redoc" if settings.DEBUG else None,
)
# Include i router con prefisso e tag per la documentazione
app.include_router(users.router, prefix="/users", tags=["users"])
app.include_router(items.router, prefix="/items", tags=["items"])
@app.get("/health", tags=["system"])
def health_check():
return {"status": "healthy", "version": settings.APP_VERSION}
Dokumentace OpenAPI: Swagger a ReDoc
FastAPI automaticky generuje dvě interaktivní dokumentační rozhraní, která můžete navštívit během vývoje:
-
Uživatelské rozhraní Swagger (
/docs): interaktivní rozhraní pro testování API přímo z prohlížeče. Podporuje ověřování, tělo JSON, parametry dotazu. -
ReDoc (
/redoc): čitelná dokumentace, ideální pro sdílet se svým týmem nebo spotřebiteli API. -
OpenAPI JSON (
/openapi.json): strojově čitelné schéma slouží ke generování klientů SDK v libovolném jazyce.
# Arricchire la documentazione con metadata aggiuntivi
from fastapi import FastAPI
from fastapi.openapi.utils import get_openapi
app = FastAPI()
# Override del schema OpenAPI per aggiungere security schemes e metadata
def custom_openapi():
if app.openapi_schema:
return app.openapi_schema
openapi_schema = get_openapi(
title="My API",
version="2.0.0",
description="Descrizione lunga dell'API con **markdown** supportato",
terms_of_service="https://example.com/terms",
contact={
"name": "Federico Calo",
"url": "https://federicocalo.dev",
"email": "info@federicocalo.dev",
},
license_info={
"name": "MIT",
"url": "https://opensource.org/licenses/MIT",
},
routes=app.routes,
)
# Aggiungi Bearer token authentication
openapi_schema["components"]["securitySchemes"] = {
"BearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT",
}
}
app.openapi_schema = openapi_schema
return app.openapi_schema
app.openapi = custom_openapi
Dokumentace ve výrobě
Vždy deaktivujte Swagger UI a ReDoc v produkci nastavením
docs_url=None e redoc_url=None v konstruktoru FastAPI.
Interaktivní dokumentace odhaluje vnitřní strukturu API a může
použít k prozkoumání nezdokumentovaných koncových bodů. Koncový bod
/openapi.json musí být chráněny stejným způsobem.
Konfigurace pomocí Pydantic Settings
Správný způsob, jak zpracovat konfiguraci ve FastAPI, je použít
pydantic-settings který automaticky čte proměnné prostředí
s ověřením typu:
# app/config.py - Configurazione type-safe con pydantic-settings
# pip install pydantic-settings
from pydantic_settings import BaseSettings, SettingsConfigDict
from functools import lru_cache
class Settings(BaseSettings):
# Valori letti da variabili d'ambiente (case insensitive)
APP_NAME: str = "My FastAPI App"
APP_VERSION: str = "1.0.0"
DEBUG: bool = False
# Database
DATABASE_URL: str # Obbligatorio: fallisce se non presente
DB_POOL_SIZE: int = 10
DB_MAX_OVERFLOW: int = 20
# Secrets
SECRET_KEY: str # Obbligatorio
ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
# CORS
ALLOWED_ORIGINS: list[str] = ["http://localhost:3000"]
model_config = SettingsConfigDict(
env_file=".env", # Legge da .env se presente
env_file_encoding="utf-8",
case_sensitive=False, # DATABASE_URL = database_url
)
# lru_cache evita di rileggere il file .env ad ogni richiesta
@lru_cache
def get_settings() -> Settings:
return Settings()
# Uso nelle route tramite Depends()
from fastapi import Depends
@app.get("/info")
def app_info(settings: Settings = Depends(get_settings)):
return {
"name": settings.APP_NAME,
"version": settings.APP_VERSION,
"debug": settings.DEBUG,
}
Závěry a další kroky
FastAPI kombinuje tři funkce, které se obecně vylučují: rychlost vývoje, typová bezpečnost a výkon. Typové rady nejsou dekorativní – slouží k ověření, dokumentaci a automatickou serializaci. To drasticky redukuje kód standardní ve srovnání s Flask nebo Django REST Framework.
Dalším krokem je pochopení asynchronního modelu, díky kterému je FastAPI rychlé
Úlohy vázané na I/O: jak fungují asyncio, smyčky událostí a korutiny a kdy je použít
async def vs def normální.
Python FastAPI a Async Web Series
- Článek 1 (tento): Nastavení, tipy pro typy a vlastní dokumentace OpenAPI
- Článek 2: Async/Await v Pythonu: smyčky událostí, korutiny a souběžnost vázaná na I/O
- Článek 3: Pydantic v2: Advanced Validation, BaseModel a TypeAdapter
- Článek 4: Vložení závislosti: Vzor pro čistý a testovatelný kód
- Článek 5: Async Database s SQLAlchemy 2.0 a Alembic







