Neden 2026'da FastAPI

FastAPI yalnızca birkaç yıl içinde deneysel bir projeden API'ler için referans çerçevesine dönüştü Python üretimde. Python Geliştiricileri Anketi 2024'e göre ikinci çerçevedir. Yayılım açısından Python web (%38), yalnızca Django tarafından geçildi. Sebepler somut: performans G/Ç bağlantılı iş yükleri için Node.js ve Go ile karşılaştırılabilir, sıfır standart veri doğrulaması Pydantic v2 ve OpenAPI belgeleri koddan otomatik olarak oluşturulur.

İşin sırrı mimaride: FastAPI üzerine inşa edilmiştir Yıldız adayları (ASGI çerçevesi) e Pdantik (Rust çekirdeği ile doğrulama). Eklemiyor işe yaramaz soyutlamalar - her özelliğin kesin bir teknik nedeni vardır.

Ne Öğreneceksiniz

  • Kurulum ve ilk FastAPI sunucusu 5 dakikada çalışıyor
  • Python türü ipuçları nasıl doğrulama, serileştirme ve belgelemeye dönüşür?
  • Pydantic ile yol parametreleri, sorgu parametreleri ve istek gövdeleri
  • Swagger Kullanıcı Arayüzü ve ReDoc: Otomatik olarak oluşturulan belgelerde gezinin
  • Durum kodları, yanıt modelleri ve temel hata yönetimi
  • Gerçek bir FastAPI projesinin yapısı (yalnızca tek bir dosya değil)

Kurulum ve İlk Sunucu

FastAPI, Python 3.8+ sürümünü gerektirir ancak gelişmiş performans için 3.11+ sürümünü öneriyoruz asyncio ve tür ipuçlarının yeni özellikleri. Uvicorn ASGI sunucusudur Yerel kalkınma için tavsiye edilir.

# 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

Mümkün olan minimum sunucu. Bunu farklı kaydet 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.

Açık http://127.0.0.1:8000/docs oluşturulan Swagger kullanıcı arayüzünü görmek için otomatik olarak. Hiçbir şeyi yapılandırmadınız: FastAPI kod açıklamalarını okudu ve eksiksiz belgeler oluşturduk.

İpuçlarını API Sözleşmesi olarak yazın

FastAPI'nin en güçlü özelliği aşağıdaki gibi Python tipi ipuçlarının kullanılmasıdır: API sözleşme tanımı. Açıklamalı her parametre otomatik olarak şu hale gelir: doğrulanmış, belgelenmiş ve serileştirilmiştir. Sıfır ek standart kod.

# 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

Pydantic Modelleriyle Gövde Talep Et

POST/PUT/PATCH isteğinin gövdesindeki veriler için Pydantic şablonları kullanılır. FastAPI, gelen JSON'u otomatik olarak seri durumdan çıkarır, şablona göre doğrular, ve onu yazılı bir Python nesnesi olarak kullanılabilir hale getirir.

# 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)

HTTPException ile Hata İşleme

FastAPI, istisnaları yapılandırılmış HTTP yanıtlarına eşler. Standart desen kullanır HTTPException beklenen hatalar ve genel bir istisna işleyicisi için beklenmeyen hatalar.

# 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"},
    )

Gerçek Bir Projenin Yapısı

Tek bir main.py öğreticiler için sorun değil, ancak gerçek bir proje için değil. Önerilen yapı, endişeleri uyumlu modüllere ayırır:

# 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}

OpenAPI belgeleri: Swagger ve ReDoc

FastAPI, ziyaret etmeniz için otomatik olarak iki etkileşimli belge arayüzü oluşturur geliştirme sırasında:

  • Havalı kullanıcı arayüzü (/docs): test için etkileşimli arayüz API'yi doğrudan tarayıcıdan kullanın. Kimlik doğrulamayı, JSON gövdesini ve sorgu parametrelerini destekler.
  • Yeniden Belgele (/redoc): okunabilir belgeler, aşağıdakiler için idealdir: ekibinizle veya API tüketicilerinizle paylaşın.
  • OpenAPI JSON (/openapi.json): makine tarafından okunabilir şema Herhangi bir dilde SDK istemcileri oluşturmak için kullanılır.
# 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

Üretimde Dokümantasyon

Swagger UI ve ReDoc'u üretimde her zaman ayarlayarak devre dışı bırakın docs_url=None e redoc_url=None FastAPI yapıcısında. Etkileşimli belgeler API'nin iç yapısını ortaya çıkarır ve belgelenmemiş uç noktaları keşfetmek için kullanılabilir. Uç nokta /openapi.json aynı şekilde korunmalıdır.

Pydantic Ayarlarıyla Yapılandırma

FastAPI'de yapılandırmayı yönetmenin doğru yolu kullanmaktır. pydantic-settings ortam değişkenlerini otomatik olarak okuyan tür doğrulama ile:

# 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,
    }

Sonuçlar ve Sonraki Adımlar

FastAPI genellikle birbirini dışlayan üç özelliği birleştirir: geliştirme hızı, Tip güvenliği ve performansı. Yazım ipuçları dekoratif değildir; doğrulamayı yönlendirir, dokümantasyon ve otomatik serileştirme. Bu, kodu büyük ölçüde azaltır Flask veya Django REST Framework ile karşılaştırıldığında ortak metin.

Bir sonraki adım, FastAPI'yi hızlı hale getiren eşzamansız modeli anlamaktır. G/Ç bağlantılı iş yükleri: zaman uyumsuzluk, olay döngüleri ve eşyordamlar nasıl çalışır ve bunların ne zaman kullanılacağı async def vs def normal.

Python FastAPI ve Async Web Serisi

  • Madde 1 (bu): Kurulum, Yazım İpuçları ve OpenAPI Kendi Kendine Belgeleme
  • Madde 2: Python'da Async/Await: Olay Döngüleri, Ortak Yordamlar ve G/Ç'ye Bağlı Eşzamanlılık
  • Madde 3: Pydantic v2: Gelişmiş Doğrulama, BaseModel ve TypeAdapter
  • Madde 4: Bağımlılık Enjeksiyonu: Temiz ve Test Edilebilir Kod Kalıbı
  • Madde 5: SQLAlchemy 2.0 ve Alembic ile Eşzamansız Veritabanı