Takip et

FastAPI ile Ciddi Düşünmeye Başladıysanız: İşte Öğrendiklerim

FastAPI ile Ciddi Düşünmeye Başladıysanız: İşte Öğrendiklerim Python ekosisteminde web API geliştirmek için birçok seçenek mevcutken, FastAPI …

FastAPI ile Ciddi Düşünmeye Başladıysanız: İşte Öğrendiklerim

Python ekosisteminde web API geliştirmek için birçok seçenek mevcutken, FastAPI son yıllarda hızla popülerlik kazandı ve birçok geliştiricinin favorisi haline geldi. Hızlı performansı, modern Python özelliklerini kullanması ve harika geliştirici deneyimi sunmasıyla öne çıkan bu framework, eğer projelerinizde ciddi bir şekilde kullanmayı düşünüyorsanız, bilmeniz gereken bazı önemli detaylar var. Bu makalede, FastAPI ile çalışırken edindiğim tecrübeleri, ipuçlarını ve en iyi uygulamaları sizlerle paylaşacağım.

1. Neden FastAPI?

FastAPI’nin bu kadar kısa sürede bu kadar büyük bir etki yaratmasının ardında yatan temel nedenleri anlamak, framework’ün felsefesini kavramanıza yardımcı olacaktır. Sadece hızlı olması değil, aynı zamanda geliştirici dostu olması da onu cazip kılıyor.

1.1. Performans ve Asenkron Yetenekler

FastAPI, Starlette (web kısmı) ve Pydantic (veri validasyonu) üzerine inşa edilmiştir. Starlette, ASGI (Asynchronous Server Gateway Interface) standardını destekleyen hafif bir web framework’üdür. Bu sayede FastAPI, Python’ın async ve await anahtar kelimelerini kullanarak asenkron I/O işlemlerini verimli bir şekilde yönetebilir. Bu, özellikle veritabanı sorguları, harici API çağrıları gibi I/O yoğun işlemlerde uygulamanızın aynı anda birden fazla isteği işlemesine olanak tanır ve performansı önemli ölçüde artırır.

1.2. Geliştirici Deneyimi ve Dokümantasyon

FastAPI’nin en büyük artılarından biri, otomatik olarak interaktif API dokümantasyonu (Swagger UI ve ReDoc) oluşturmasıdır. Bu, hem API geliştiricileri hem de API’yi tüketen frontend veya mobil geliştiriciler için paha biçilmez bir kolaylık sağlar. Parametrelerin, istek gövdelerinin ve yanıtların otomatik olarak şematize edilmesi, hataları azaltır ve entegrasyon sürecini hızlandırır.

1.3. Modern Python Özellikleri

FastAPI, Python’ın tip ipuçlarını (type hints) yoğun bir şekilde kullanır. Bu, kodunuzun daha okunabilir, bakımı daha kolay olmasını sağlar ve IDE’lerin otomatik tamamlama (autocompletion) özelliklerinden tam olarak faydalanmanızı sağlar. Pydantic ile birleştiğinde, tip ipuçları veri validasyonu ve serileştirme için de temel oluşturur.

2. Temelleri Anlamak: Asenkron Programlama ve Pydantic

FastAPI’nin gücünü tam olarak kullanabilmek için Python’daki asenkron programlama ve Pydantic veri modellerini iyi kavramak şarttır. Bunlar, framework’ün temel yapı taşlarıdır.

2.1. async/await ve ASGI

Python’da async def ile tanımlanan fonksiyonlar “coroutine” olarak adlandırılır ve await anahtar kelimesi ile başka bir coroutine’in tamamlanmasını bekleyebilirler. FastAPI, bu yapıyı kullanarak gelen istekleri eşzamansız olarak işler. Eğer bir endpoint’inizde I/O yoğun bir işlem yapmıyorsanız bile, async def kullanmak iyi bir alışkanlıktır, çünkü bu, ASGI sunucusunun (Uvicorn gibi) bu endpoint’i eşzamansız bir bağlamda çalıştırmasına olanak tanır.

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
    return {"message": "Merhaba Dünya!"}

@app.get("/items/{item_id}")
async def read_item(item_id: int, q: str = None):
    # Bu kısımda bir veritabanı sorgusu veya harici API çağrısı olabilir
    # await db.fetch_one(...)
    return {"item_id": item_id, "q": q}

2.2. Pydantic Modelleri ile Veri Tanımlama

Pydantic, Python'ın tip ipuçlarını kullanarak veri validasyonu, serileştirme ve dokümantasyon sağlayan bir kütüphanedir. FastAPI, istek gövdelerini ve yanıt modellerini tanımlamak için Pydantic'i kullanır. Bir BaseModel sınıfından türeterek, veri yapılarınızı kolayca tanımlayabilirsiniz.

from pydantic import BaseModel

class Item(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

@app.post("/items/")
async def create_item(item: Item):
    return item

Bu örnekte, Item sınıfı, name'in string, price'ın float olması gerektiğini belirtir. description ve tax ise isteğe bağlıdır. FastAPI, gelen JSON verisini otomatik olarak bu modele göre valide eder.

2.3. Path ve Query Parametreleri

FastAPI, URL yolundaki (path) ve sorgu dizesindeki (query string) parametreleri kolayca tanımlamanızı sağlar. Tip ipuçları sayesinde, parametrelerin tipleri otomatik olarak doğrulanır ve dönüştürülür.

from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/users/{user_id}")
async def get_user(user_id: int, limit: int = Query(10, ge=1, le=100)):
    # user_id bir path parametresi, limit bir query parametresi
    # limit değeri 1 ile 100 arasında olmalı, varsayılanı 10
    return {"user_id": user_id, "limit": limit}

3. Bağımlılık Enjeksiyonu: Temiz Kodun Anahtarı

FastAPI'nin en güçlü özelliklerinden biri, bağımlılık enjeksiyonu (Dependency Injection) sistemidir. Bu sistem, kodunuzu daha modüler, test edilebilir ve yeniden kullanılabilir hale getirir.

3.1. Depends Fonksiyonu

fastapi.Depends fonksiyonu, bir endpoint fonksiyonunun başka bir fonksiyondan veya sınıftan bir değer almasını sağlar. Bu "bağımlılık" otomatik olarak çözülür ve endpoint'e enjekte edilir.

from fastapi import FastAPI, Depends, HTTPException, status

app = FastAPI()

async def get_current_user(token: str):
    # Gerçek bir uygulamada token'ı doğrular ve kullanıcıyı döner
    if token != "secret_token":
        raise HTTPException(
            status_code=status.HTTP_401_UNAUTHORIZED,
            detail="Geçersiz kimlik bilgileri",
            headers={"WWW-Authenticate": "Bearer"},
        )
    return {"username": "testuser"}

@app.get("/me/")
async def read_users_me(current_user: dict = Depends(get_current_user)):
    return current_user

Bu örnekte, get_current_user fonksiyonu bir bağımlılık olarak tanımlanmıştır. /me/ endpoint'ine yapılan her istekte, get_current_user çalışacak ve döndürdüğü değer current_user parametresine atanacaktır.

3.2. Veritabanı Bağlantıları ve Servis Katmanları

Bağımlılık enjeksiyonu, veritabanı oturumları, servis katmanları veya diğer kaynakları yönetmek için idealdir. Örneğin, her istek için bir veritabanı oturumu oluşturup kapatabilirsiniz.

from sqlalchemy.orm import Session
from database import SessionLocal, engine # Kendi veritabanı bağlantı kodunuz

# Veritabanı oturumu için bir bağımlılık
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.get("/db_items/")
async def read_db_items(db: Session = Depends(get_db)):
    # Veritabanı işlemleri yapın
    items = db.query(models.Item).all()
    return items

3.3. Güvenlik Bağımlılıkları

Kimlik doğrulama ve yetkilendirme gibi güvenlik mekanizmaları da bağımlılık olarak kolayca entegre edilebilir. OAuth2, JWT gibi standartları uygulamak için FastAPI'nin güvenlik yardımcıları (örneğin Security veya OAuth2PasswordBearer) ile birlikte Depends kullanılır.

4. Veri Validasyonu ve Serileştirme: Pydantic'in Gücü

Pydantic, FastAPI'nin temelini oluşturan ve veri yönetimi konusunda size büyük kolaylıklar sağlayan bir kütüphanedir.

4.1. Request Body ve Response Modelleri

Pydantic modelleri sadece gelen istek gövdelerini valide etmekle kalmaz, aynı zamanda API yanıtlarının yapısını tanımlamak için de kullanılabilir. Bu, tutarlı bir API arayüzü sağlamanın yanı sıra, otomatik dokümantasyonda da doğru bilgilerin yer almasını garantiler.

from pydantic import BaseModel

class ItemCreate(BaseModel):
    name: str
    description: str | None = None
    price: float
    tax: float | None = None

class ItemResponse(ItemCreate): # Yanıt modelinde id gibi ek alanlar olabilir
    id: int

@app.post("/items/", response_model=ItemResponse)
async def create_item(item: ItemCreate):
    # Veritabanına kaydetme işlemi
    new_item_id = 1 # Örnek ID
    return ItemResponse(id=new_item_id, **item.dict())

response_model parametresi, FastAPI'ye endpoint'ten dönecek veriyi hangi Pydantic modeline göre serileştireceğini ve dokümante edeceğini söyler.

4.2. Özel Validasyon Kuralları

Pydantic, alanlar üzerinde özel validasyon kuralları tanımlamanıza olanak tanır. @validator dekoratörü veya modelin Config sınıfı ile daha karmaşık doğrulama mantığı ekleyebilirsiniz.

from pydantic import BaseModel, validator

class User(BaseModel):
    username: str
    email: str

    @validator('email')
    def validate_email_domain(cls, v):
        if not v.endswith("@example.com"):
            raise ValueError("Sadece @example.com uzantılı e-postalar kabul edilir")
        return v

4.3. Model Nesting ve İlişkiler

Pydantic modelleri iç içe geçebilir, bu da karmaşık veri yapılarını kolayca tanımlamanızı sağlar. Bu, ilişkisel veritabanı modellerini veya karmaşık JSON yapılarını temsil etmek için oldukça kullanışlıdır.

class Address(BaseModel):
    street: str
    city: str
    zip_code: str

class Customer(BaseModel):
    name: str
    email: str
    address: Address # İç içe geçmiş Pydantic modeli

5. Gelişmiş Özellikler ve En İyi Uygulamalar

FastAPI, temel API geliştirmenin ötesinde, uygulamanızı daha sağlam ve ölçeklenebilir hale getirecek birçok gelişmiş özellik sunar.

5.1. Router'lar ve Uygulama Yapısı

Büyük uygulamalarda tüm endpoint'leri tek bir dosyada tutmak yerine, APIRouter kullanarak uygulamanızı modüler parçalara ayırabilirsiniz. Her bir modül (örneğin users.py, items.py) kendi router'ına sahip olabilir ve ana FastAPI uygulamasına dahil edilebilir.

# app/routers/items.py
from fastapi import APIRouter

router = APIRouter(prefix="/items", tags=["items"])

@router.get("/")
async def read_items():
    return [{"item_id": "Foo"}, {"item_id": "Bar"}]

# app/main.py
from fastapi import FastAPI
from app.routers import items

app = FastAPI()
app.include_router(items.router)

5.2. Middleware Kullanımı

Middleware'ler, her istekten önce veya sonra belirli işlemleri gerçekleştirmek için kullanılır. Örneğin, loglama, kimlik doğrulama, CORS (Cross-Origin Resource Sharing) başlıkları ekleme gibi görevler için idealdir.

from fastapi import FastAPI, Request
from starlette.middleware.cors import CORSMiddleware
import time

app = FastAPI()

# CORS Middleware
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"], # Gerçek uygulamada belirli origin'leri belirtin
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Özel bir 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

5.3. Arka Plan Görevleri (Background Tasks)

Bir API isteği tamamlandıktan sonra, kullanıcının yanıt beklemesini gerektirmeyen uzun süreli işlemler için arka plan görevlerini kullanabilirsiniz. Örneğin, e-posta gönderme veya dosya işleme.

from fastapi import FastAPI, BackgroundTasks

app = FastAPI()

def write_notification(email: str, message: str = ""):
    with open("log.txt", mode="a") as email_file:
        content = f"notification for {email}: {message}\n"
        email_file.write(content)

@app.post("/send-notification/{email}")
async def send_notification(email: str, background_tasks: BackgroundTasks):
    background_tasks.add_task(write_notification, email, message="some notification")
    return {"message": "Notification sent in the background"}

5.4. WebSockets

FastAPI, Starlette sayesinde WebSocket iletişimini de kolayca destekler. Gerçek zamanlı uygulamalar (chat uygulamaları, canlı veri akışları) için kullanışlıdır.

from fastapi import FastAPI, WebSocket

app = FastAPI()

@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
    await websocket.accept()
    while True:
        data = await websocket.receive_text()
        await websocket.send_text(f"Mesajınız: {data}")

6. Test Etme ve Dağıtım

Herhangi bir ciddi uygulamanın ayrılmaz bir parçası olan test ve dağıtım süreçleri, FastAPI ile oldukça düzgündür.

6.1. TestClient ile Birim ve Entegrasyon Testleri

FastAPI, Starlette'in TestClient sınıfını kullanarak API endpoint'lerinizi kolayca test etmenizi sağlar. Bu, gerçek bir HTTP isteği göndermeden, uygulamanızın dahili olarak nasıl yanıt verdiğini kontrol etmenizi sağlar.

from fastapi.testclient import TestClient
from main import app # main.py dosyanızdaki FastAPI uygulamanız

client = TestClient(app)

def test_read_main():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"message": "Merhaba Dünya!"}

def test_read_item():
    response = client.get("/items/1?q=test")
    assert response.status_code == 200
    assert response.json() == {"item_id": 1, "q": "test"}

6.2. Docker ile Konteynerleştirme

FastAPI uygulamalarını Docker ile konteynerleştirmek, dağıtım sürecini basitleştirir ve ortam bağımlılıklarını yönetmeyi kolaylaştırır. Bir Dockerfile ile uygulamanızı ve bağımlılıklarını tek bir taşınabilir birimde paketleyebilirsiniz.

# Dockerfile örneği
FROM python:3.9-slim-buster

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]

6.3. Uvicorn ve Gunicorn ile Üretim Ortamı

FastAPI uygulamalarını üretimde çalıştırmak için bir ASGI sunucusu (örneğin Uvicorn) ve genellikle bir süreç yöneticisi (örneğin Gunicorn) kullanmanız önerilir. Gunicorn, Uvicorn worker'larını yöneterek uygulamanızın daha sağlam ve ölçeklenebilir olmasını sağlar.

# Uvicorn ile çalıştırma (tek worker)
uvicorn main:app --host 0.0.0.0 --port 8000

# Gunicorn ve Uvicorn worker'ları ile çalıştırma (çoklu worker)
gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000

7. Sık Karşılaşılan Zorluklar ve Çözümleri

FastAPI ile çalışırken karşılaşabileceğiniz bazı yaygın sorunlar ve bunlara yönelik çözümler.

7.1. Asenkron Kodda Hatalar

* Sorun: Senkron bir fonksiyonu await ile çağırmaya çalışmak veya async def içinde await kullanmamak.
* Çözüm: async def ile tanımlanan her fonksiyonun içinde, I/O blokajı yaratabilecek her işlemi await ile çağırdığınızdan emin olun. Eğer üçüncü parti bir kütüphane senkron ise ve onu async def içinde kullanmanız gerekiyorsa, run_in_threadpool gibi mekanizmalarla onu ayrı bir thread'de çalıştırmayı düşünebilirsiniz (ancak bu, asenkron yapıyı bozabilir).

7.2. Büyük Uygulamalarda Yapılandırma

* Sorun: Uygulama büyüdükçe, yapılandırma (ayarlar, veritabanı URL'leri vb.) yönetimi zorlaşabilir.
* Çözüm: pydantic-settings (eski adıyla pydantic-settings) kütüphanesini kullanarak ortam değişkenleri, .env dosyaları ve varsayılan değerler ile yapılandırmayı merkezi ve tip güvenli bir şekilde yönetin.

7.3. Veritabanı Entegrasyonları

* Sorun: SQLAlchemy gibi ORM'leri asenkron bağlamda kullanırken blokaj sorunları yaşamak.
* Çözüm: Asenkron veritabanı sürücüleri ve ORM'ler kullanın. Örneğin, SQLAlchemy için asyncpg ile asyncio desteği veya databases kütüphanesi gibi çözümler mevcuttur. Tortoise ORM veya SQLModel (FastAPI'nin yaratıcısı tarafından geliştirilen Pydantic ve SQLAlchemy tabanlı ORM) gibi tamamen asenkron ORM'ler de iyi seçeneklerdir.

Sonuç

FastAPI, modern web API geliştirmeyi hızlı, verimli ve keyifli hale getiren güçlü bir framework'tür. Asenkron yetenekleri, Pydantic ile entegre veri validasyonu, kapsamlı bağımlılık enjeksiyonu sistemi ve otomatik dokümantasyonu sayesinde, hem küçük prototipler hem de büyük ölçekli kurumsal uygulamalar için mükemmel bir seçimdir. Eğer Python ile API geliştirmeye ciddi bir şekilde yaklaşıyorsanız, FastAPI'yi derinlemesine öğrenmek, geliştirme sürecinizi önemli ölçüde hızlandıracak ve uygulamanızın kalitesini artıracaktır. Unutmayın, en iyi uygulamaları takip etmek ve framework'ün temel prensiplerini anlamak, uzun vadede size büyük faydalar sağlayacaktır.

SSS (Sık Sorulan Sorular)

FastAPI'nin en büyük avantajı nedir?
En büyük avantajı, performanslı asenkron yapısı, Pydantic ile gelen otomatik veri validasyonu ve serileştirme, ve Swagger/ReDoc ile otomatik interaktif API dokümantasyonu sunmasıdır.
FastAPI ile hangi veritabanlarını kullanabilirim?
FastAPI, herhangi bir veritabanı ile uyumludur. SQLAlchemy (senkron veya asenkron), Tortoise ORM, SQLModel, Pymongo gibi birçok kütüphaneyi kullanabilirsiniz. Seçiminiz projenizin ihtiyaçlarına ve tercih ettiğiniz ORM/ODM'ye bağlıdır.
FastAPI'yi üretimde kullanmak güvenli midir?
Kesinlikle evet. FastAPI, modern Python standartlarını ve güvenlik en iyi uygulamalarını takip eder. Kimlik doğrulama, yetkilendirme, CORS gibi güvenlik mekanizmalarını kolayca entegre edebilirsiniz. Önemli olan, uygulamanızın kendi güvenlik açıklarını (örneğin, zayıf şifreleme, SQL enjeksiyonu) yönetmektir.
FastAPI mi, Flask mı yoksa Django mu tercih etmeliyim?
Seçim, projenizin gereksinimlerine bağlıdır:

  • FastAPI: Yüksek performanslı, asenkron API'ler için idealdir. Otomatik dokümantasyon ve veri validasyonu arıyorsanız.
  • Flask: Mikro servisler veya daha küçük API'ler için hafif ve esnektir. Daha fazla manuel yapılandırma gerektirir.
  • Django: Kapsamlı web uygulamaları (tam teşekküllü web siteleri, admin panelleri) ve ORM, formlar, kimlik doğrulama gibi "pil dahil" çözümler arıyorsanız.
FastAPI'de hata yönetimi nasıl yapılır?
FastAPI, HTTPException sınıfını kullanarak standart HTTP hatalarını kolayca döndürmenizi sağlar. Ayrıca, @app.exception_handler dekoratörü ile özel hata işleyicileri tanımlayarak belirli hata türlerini yakalayıp özelleştirilmiş yanıtlar verebilirsiniz.
Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.