Sıfırdan FastAPI: Kurulum, Yazım İpuçları ve OpenAPI Kendi Kendine Belgeleme
Bir FastAPI projesini 5 dakikadan kısa sürede nasıl başlatacağınızı öğrenin: ipuçlarını API sözleşmesi olarak yazın, Veri doğrulama ve otomatik olarak oluşturulan Swagger belgeleri için Pydantic v2 ekstra yapılandırma olmadan.
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ı







