Ana içeriğe atla

Pydantic: Uygulamalı Örneklerle Bir Rehber

Pydantic’in ne olduğunu, ne için kullanıldığını ve Marshmallow veya Python’un dataclass’ları gibi alternatiflerle nasıl karşılaştırıldığını öğrenin.
Güncel 12 May 2026  · 12 dk. oku

Pydantic, tür ipuçlarını çalışma zamanında doğrulama kurallarına dönüştürebilen Python’un en popüler veri doğrulama kitaplığıdır.

Onlarca if isinstance() kontrolü ve özel doğrulama fonksiyonu yazmak yerine, tanıdık Python sözdizimiyle veri yapınızı bir kez tanımlarsınız.

Gerisini Pydantic halleder: gelen verileri doğrular, uygun olduğunda tür dönüşümü yapar ve doğrulama başarısız olduğunda net hata mesajları sağlar.

Tür ipuçlarına ve düzgün belgelenmiş bir imzaya sahip bu basit Python fonksiyonunu düşünün:

def calculate_user_discount(age: int, is_premium_member: bool, purchase_amount: float) -> float:
   """Calculate discount percentage based on user profile and purchase amount."""
   if age >= 65:
       base_discount = 0.15
   elif is_premium_member:
       base_discount = 0.10
   else:
       base_discount = 0.05
  
   return purchase_amount * base_discount

İmzasına bakarak, tam olarak hangi tür verileri kabul ettiğini ve diğer uçta ne ürettiğini bilirsiniz. Peki son kullanıcı için de aynısını söyleyebilir misiniz? Sonuçta bu tür ipuçları sadece belgeleme amaçlıdır — biri yanlış veri türü gönderirse, Python yorumlayıcısı bunu hiç umursamaz:

# Türler tamamen yanlış olsa bile bu hata vermeden çalışır!
discount = calculate_user_discount(True, 1, 5)
print(discount)  # Output: 0.5 (True 1'e dönüşür, 1 truthy'dir, dolayısıyla 5 * 0.10)

Bu, Python’un dinamik türlendirmesinin klasik bir örneğidir. Geliştiricilere hızlı geliştirme ve özgürlük sunar, ancak bunun bedeli genellikle üretimde ortaya çıkan tür doğrulama sorunlarıdır.

Bu eğitimde, Pydantic’i gerçek dünya uygulamalarında nasıl kullanacağınızı açıklayacağım. İlk veri modelinizle başlayıp üretim sistemlerinde kullanılan ileri düzey kalıplara doğru ilerleyeceğiz. İç içe geçmiş veri yapılarının nasıl doğrulanacağını, karmaşık iş kuralları için özel doğrulayıcıların nasıl yazılacağını ve Pydantic’in FastAPI ve SQLAlchemy gibi popüler çerçevelerle nasıl entegre edileceğini keşfedeceksiniz.

Aşağıda, Pydantic’in temellerine dair video eğitimimizi de izleyebilirsiniz.

Pydantic Nedir?

Dış dünya ile etkileşime giren uygulamalar geliştirdiğinizde aslında bir veri ruleti oynarsınız. Kullanıcılar telefon numarasını tamsayı yerine metin olarak gönderebilir, bir API beklediğiniz yerlerde sayı yerine null dönebilir ya da bir yapılandırma dosyasındaki yazım hatası uygulamanızı sabaha karşı 3’te bozabilir.

Bu soruna yönelik geleneksel Python yaklaşımları hızla kontrol edilemez hale gelir. Sonunda şöyle doğrulama kodları yazarken bulursunuz kendinizi:

def create_user(data):
   # Elle doğrulama kabusu
   if not isinstance(data.get('age'), int):
       raise ValueError("Age must be an integer")
   if data['age'] < 0 or data['age'] > 150:
       raise ValueError("Age must be between 0 and 150")
   if not isinstance(data.get('email'), str) or '@' not in data['email']:
       raise ValueError("Invalid email format")
   if not isinstance(data.get('is_active'), bool):
       raise ValueError("is_active must be a boolean")
  
   # Sonunda kullanıcıyı oluştur...
   return User(data['age'], data['email'], data['is_active'])

Bunu uygulamanızdaki her veri yapısı için katlayın; iş mantığından çok doğrulama kodu yazmaya vakit harcarsınız.

Pydantic, üç güçlü kavramı birleştirerek bunu çözer: tür ipuçları, çalışma zamanı doğrulaması ve otomatik serileştirme. Elle kontrol yerine, veri yapınızı Python’un tür ek açıklama sözdizimiyle bir kez tanımlarsınız ve Pydantic tüm doğrulamayı otomatik yapar:

from pydantic import BaseModel, EmailStr
from typing import Optional

class User(BaseModel):
   age: int
   email: EmailStr
   is_active: bool = True
   nickname: Optional[str] = None

# Pydantic verileri otomatik doğrular ve dönüştürür
user_data = {
   "age": "25",  # Metin int'e dönüştürülür
   "email": "john@example.com",
   "is_active": "true"  # Metin bool'a dönüştürülür
}

user = User(**user_data)
print(user.age)  # 25 (int olarak)
print(user.model_dump())  # Temiz sözlük çıktısı

Pydantic’in özellikleri

Pydantic’in yaklaşımı size birkaç fayda sağlar. İlk fark edeceğiniz avantaj performanstır — Pydantic’in çekirdek doğrulama mantığı Rust ile yazılmıştır; bu da çoğu durumda elle yazılmış Python doğrulamasından daha hızlı olmasını sağlar. Uygulamanız doğrulama darboğazı olmadan binlerce isteği işleyebilir.

Pydantic ayrıca modern çerçevelerle entegrasyona izin verir. Python’un en hızlı büyüyen web çerçevelerinden biri olan FastAPI, Pydantic modellerini kullanarak API dokümantasyonunu otomatik üretir, istek gövdelerini doğrular ve yanıtları serileştirir. Bir Pydantic modeli tanımladığınızda, OpenAPI şema üretimini de bedavaya alırsınız:

from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()

class UserCreate(BaseModel):
   name: str
   email: EmailStr
   age: int

@app.post("/users/")
async def create_user(user: UserCreate):
   # FastAPI, istek gövdesini otomatik doğrular
   # ve Pydantic modelinizden API dokümanları üretir
   return {"message": f"Created user {user.name}"}

JSON şema üretimi her Pydantic modeliyle otomatik gerçekleşir. Bu, veri yapılarınızın kendi kendini belgelediği ve aynı bilgi kaynağından istemci kütüphaneleri, ön uç uygulamaları için doğrulama kuralları veya veritabanı şemaları üretebileceğiniz anlamına gelir.

Pydantic vs. Dataclasses vs. Marshmallow

Peki ne zaman Pydantic’i alternatiflere tercih etmelisiniz? Pydantic ile dataclasses karşılaştırmasında karar, doğrulama ihtiyacına bağlıdır. Python’un @dataclass’ı, girdiye güvendiğiniz basit veri kapları için idealdir; ancak doğrulama, serileştirme ve web çerçeveleriyle entegrasyon gerektiğinde Pydantic üstün gelir:

from dataclasses import dataclass
from pydantic import BaseModel

# Dataclass: hızlı, basit, doğrulama yok
@dataclass
class UserDataclass:
   name: str
   age: int

# Pydantic: doğrulama, serileştirme, çerçeve entegrasyonu
class UserPydantic(BaseModel):
   name: str
   age: int

Pydantic’i Marshmallow ile karşılaştırırken, Pydantic’in tür ipuçlarına dayalı yaklaşımı Python geliştiricilerine daha doğal gelirken, Marshmallow şema sınıfları kullanır. Pydantic ayrıca daha iyi performans ve modern asenkron çerçevelerle daha kolay entegrasyon sunar.

Pydantic; API’ler oluştururken, harici verileri işlerken, yapılandırma yönetirken veya doğrulama hatalarının gizemli hatalara dönüşmeden erken yakalanması gereken her senaryoda en iyi sonucu verir. Çalışma zamanı hatalarını, geliştiricilerin ve kullanıcıların neyin yanlış gittiğini anlamasına yardımcı olan net ve eyleme dönük doğrulama mesajlarına dönüştürür.

Pydantic ile Başlarken

Kurulumdan ilk veri modellerinizi oluşturmaya kadar, Pydantic’i projelerinizde nasıl kullanacağınıza dalalım.

Kurulum ve yapılandırma

Pydantic’i kurmak basittir, ancak birkaç yaygın tuzak yeni başlayanların ayağına dolanabilir. Sizi doğru kurulum sürecinde adım adım yönlendireceğim ve gereksiz hata ayıklamaya yol açan hatalardan kaçınmanıza yardımcı olacağım.

Öncelikle, proje bağımlılıklarını izole etmek için bir sanal ortam oluşturun. Bu, daha sonra gizemli içe aktarma hatalarına neden olabilecek sürüm çakışmalarını önler:

# Sanal ortam oluşturma ve etkinleştirme (zsh ve bash'te çalışır)
python -m venv pydantic_env
source pydantic_env/bin/activate  # macOS/Linux'ta
# pydantic_env\Scripts\activate  # Windows'ta

Şimdi, Pydantic’i aşağıdaki komutla kurun:

pip install pydantic

Gerçek uygulamalarda (ve bu eğitimde) büyük ihtimalle ihtiyaç duyacağınız e-posta doğrulama işlevselliği için e-posta eklerini kurun:

pip install "pydantic[email]"

pydantic[email] ifadesinin etrafındaki tırnaklar neredeyse tüm terminallerde önemlidir. Onlar olmadan "no matches found" hatası görebilirsiniz.

Not: ModuleNotFoundError: No module named 'pydantic' hatasıyla karşılaşırsanız şu noktaları kontrol edin:

  1. Yanlış Python ortamı: Sanal ortamınızın etkin olduğundan emin olun
  2. Birden fazla Python sürümü: Pydantic’i kuran Python sürümünü kullandığınızı doğrulayın
  3. IDE yapılandırması: Kod düzenleyiciniz farklı bir Python yorumlayıcısı kullanıyor olabilir

Kritik adlandırma uyarısı: Python dosyanızın adını asla pydantic.py koymayın. Bu, kafa karıştırıcı hata mesajlarıyla kodunuzu bozacak döngüsel bir içe aktarma yaratır. Python, gerçek Pydantic kitaplığı yerine sizin dosyanızı içe aktarmaya çalışır.

İlk Pydantic modeliniz

Pydantic’i iş başında görmek için basit bir kullanıcı modeli oluşturalım. Soyut örneklerle başlamak yerine, gerçek bir sorunu çözeceğiz: bir web formundan gelen kullanıcı kayıt verilerini doğrulamak.

from pydantic import BaseModel, EmailStr
from typing import Optional
from datetime import datetime

class User(BaseModel):
   name: str
   email: EmailStr
   age: int
   is_active: bool = True
   created_at: datetime = None

# Temiz verilerle test
clean_data = {
   "name": "Alice Johnson",
   "email": "alice@example.com",
   "age": 28
}

user = User(**clean_data)
print(f"User created: {user.name}, Age: {user.age}")
print(f"Model output: {user.model_dump()}")

Çıktı:

User created: Alice Johnson, Age: 28
Model output: {'name': 'Alice Johnson', 'email': 'alice@example.com', 'age': 28, 'is_active': True, 'created_at': None}

Bu model tanımında neler olduğuna bakalım:

  • Pydantic modeli oluşturma: User sınıfınız BaseModel’den miras alır; bu da ona Pydantic’in tüm doğrulama ve serileştirme yeteneklerini kazandırır. Bu kalıtım, sıradan bir Python sınıfını bir veri doğrulama aracına dönüştürür.
  • Alan tanımları: Sınıftaki her satır beklenen türüyle birlikte bir alan tanımlar. name: str sözdizimi, name’in metin olması gerektiğini; age: int ise yaşın tamsayı olması gerektiğini söyler, vb.
  • EmailStr açıklaması: EmailStr, e-posta adreslerini otomatik olarak doğrulayan özel bir Pydantic türüdür. Daha önce kurduğunuz pydantic[email] paketinden gelir ve e-posta biçiminin geçerli olmasını sağlamak için düzenli ifadeler kullanır. Biri "not-an-email" gönderirse, Pydantic bir doğrulama hatası yükseltir.
  • Varsayılan değerler: is_active: bool = True gibi alanların varsayılan değerleri vardır. Bir kullanıcı oluştururken bu alanları sağlamazsanız, Pydantic varsayılanları kullanır. created_at için = None bu alanı isteğe bağlı yapar.
  • Modelin örneklenmesi: User(**clean_data) çağrısı, ** ile sözlüğünüzü açar ve her anahtar-değer çiftini model kurucusuna anahtar argüman olarak geçirir.

Şimdi Pydantic’in otomatik tür dönüşümünü iş başında görelim:

# Dağınık ama yine de çalışan veriler
messy_data = {
   "name": "Bob Smith",
   "email": "bob@company.com",
   "age": "35",  # int yerine metin
   "is_active": "true"  # bool yerine metin
}

user = User(**messy_data)
print(f"Age type: {type(user.age)}")  # <class 'int'>
print(f"Is active type: {type(user.is_active)}")  # <class 'bool'>

Şimdi Pydantic’in otomatik tür dönüşümünü iş başında görelim:

# Dağınık ama yine de çalışan veriler
messy_data = {
   "name": "Bob Smith",
   "email": "bob@company.com",
   "age": "35",  # int yerine metin
   "is_active": "true"  # bool yerine metin
}

user = User(**messy_data)
print(f"Age type: {type(user.age)}")  # <class 'int'>
print(f"Is active type: {type(user.is_active)}")  # <class 'bool'>

Çıktı:

Age type: <class 'int'>

Is active type: <class 'bool'>

Gördüğünüz gibi, age ve is_inactive alanları doğrulama sırasında otomatik olarak uygun biçimlerine dönüştürülür.

Doğrulama başarısız olduğunda Pydantic net hata mesajları sağlar:

from pydantic import ValidationError

try:
   invalid_user = User(
       name="",  # Boş metin
       email="not-an-email",  # Geçersiz e-posta
       age=-5  # Negatif yaş
   )
except ValidationError as e:
   print(e)

Çıktı:

   # Hangi alanların neden hatalı olduğunu tam olarak gösterir
1 validation error for User
email
 value is not a valid email address: An email address must have an @-sign. [type=value_error, input_value='not-an-email', input_type=str]

BaseModel vs. data class’lar

Pydantic’in BaseModel’ini ne zaman, Python’un @dataclass’ını ne zaman kullanmanız gerektiğini anlamak, her durumda doğru aracı seçmenize yardımcı olur.

Python dataclass’ları, girdiyi kontrol ettiğiniz basit veri kapları için mükemmeldir:

from dataclasses import dataclass

@dataclass
class ProductDataclass:
   name: str
   price: float
   in_stock: bool

# Hızlı, basit, ama doğrulama yok
product = ProductDataclass("Laptop", 999.99, True)

# Türler yanlış olsa bile bu da çalışır:
broken_product = ProductDataclass(123, "expensive", "maybe")

Pydantic modelleri doğrulama, serileştirme ve çerçeve entegrasyonu ekler:

from pydantic import BaseModel, Field

class ProductPydantic(BaseModel):
   name: str = Field(min_length=1)
   price: float = Field(gt=0)  # 0'dan büyük olmalı
   in_stock: bool

# Otomatik doğrulama kötü verileri engeller
try:
   product = ProductPydantic(name="", price=-10, in_stock="maybe")
except ValidationError as e:
   print("Validation caught the errors!")

# Geçerli veriler sorunsuz çalışır
good_product = ProductPydantic(
   name="Laptop",
   price="999.99",  # Metin float'a dönüştürülür
   in_stock=True
)

Hangi yaklaşımı ne zaman seçmeli:

  • Dataclass’ları dahili veri yapıları, yapılandırma nesneleri veya performansın kritik olduğu ve veri kaynaklarına güvendiğiniz durumlar için kullanın
  • Pydantic’i API uç noktaları, kullanıcı girişi, harici veri ayrıştırma veya JSON serileştirme gerektiğinde kullanın

Pydantic, dataclass’lara kıyasla bir miktar ek yük getirir; ancak bu maliyet, önlediği hatalar ve kazandırdığı geliştirme zamanı yanında genellikle ihmal edilebilir düzeydedir. Web uygulamaları için, FastAPI gibi çerçevelerle otomatik entegrasyon Pydantic’i bariz tercih haline getirir.

Uygulamanız büyüdükçe doğrulama ve serileştirme özellikleri daha değerli hale gelir. Pydantic modelleriyle başlamak, ihtiyaçlarınızla birlikte ölçeklenen sağlam bir temel sunar.

Pydantic ile Veri Modelleri Oluşturma

Artık temelleri anladığınıza göre, üretime hazır uygulamalar geliştirirken karşılaşacağınız zorlukların üstesinden gelelim.

Alan doğrulama ve kısıtlar

Fiyat verilerinin farklı biçimlendirme standartlarına sahip birden çok tedarikçiden geldiği bir ürün katalogu API’sini düşünün. Bazıları fiyatları metin, bazıları ondalık sayı olarak gönderir ve ara sıra biri negatif fiyat gönderir; bu da faturalama sisteminizi çökertir.

Pydantic’in Field() fonksiyonu, temel tür ipuçlarını uygulamanızı koruyan sofistike doğrulama kurallarına dönüştürür:

from pydantic import BaseModel, Field
from decimal import Decimal
from typing import Optional

class Product(BaseModel):
   name: str = Field(min_length=1, max_length=100)
   price: Decimal = Field(gt=0, le=10000)  # 0'dan büyük, 10.000'e eşit veya daha küçük
   description: Optional[str] = Field(None, max_length=500)
   category: str = Field(..., pattern=r'^[A-Za-z\s]+$')  # Sadece harf ve boşluk
   stock_quantity: int = Field(ge=0)  # 0 veya daha büyük
   is_available: bool = True

# Bu çalışır - tüm kısıtlar sağlanır
valid_product = Product(
   name="Wireless Headphones",
   price="199.99",  # Metin Decimal'e dönüştürülür
   description="High-quality wireless headphones",
   category="Electronics",
   stock_quantity=50
)

# Bu, net hata mesajlarıyla başarısız olur
try:
   invalid_product = Product(
       name="",  # Çok kısa
       price=-50,  # Negatif fiyat
       category="Electronics123",  # Rakam içeriyor
       stock_quantity=-5  # Negatif stok
   )
except ValidationError as e:
   print(f"Validation errors: {len(e.errors())} issues found")

Her Field() parametresi belirli bir amaca hizmet eder: min_length ve max_length veritabanı şeması ihlallerini önler; gt ve le iş mantığı sınırları oluşturur; pattern düzenli ifadeler kullanarak biçimlendirilmiş verileri doğrular. Üç noktalı Field(...) sözdizimi zorunlu alanları işaretlerken, Field(None, ...) doğrulama kuralları olan isteğe bağlı alanlar oluşturur.

Tür zorlama (coercion) vs. sıkı doğrulama

Varsayılan olarak Pydantic, uyumlu türleri doğrudan reddetmek yerine dönüştürür. Bu esneklik kullanıcı girdisi için iyi çalışır; ancak bazı senaryolar tam tür eşleşmesi gerektirir:

from pydantic import BaseModel, Field, ValidationError

# Varsayılan: esnek tür dönüştürme
class FlexibleOrder(BaseModel):
   order_id: int
   total_amount: float
   is_paid: bool

# Otomatik dönüşüm sayesinde bunların hepsi çalışır
flexible_order = FlexibleOrder(
   order_id="12345",  # Metin int'e
   total_amount="99.99",  # Metin float'a
   is_paid="true"  # Metin bool'a
)

# Hassasiyet gerektiğinde sıkı doğrulama
class StrictOrder(BaseModel):
   model_config = {"str_strip_whitespace": True, "validate_assignment": True}
  
   order_id: int = Field(strict=True)
   total_amount: float = Field(strict=True)
   is_paid: bool = Field(strict=True)

model_config sözlüğü, tüm modelinizdeki doğrulama davranışını kontrol eder. str_strip_whitespace seçeneği metin girdisini otomatik temizlerken, validate_assignment model oluşturulduktan sonra alan değişimlerinin de doğrulamayı tetiklemesini sağlar. Tekil alanlar, finansal hesaplamalar veya bilimsel veriler gibi tam tür eşleşmesi gereken durumlar için Field(strict=True) ile bu ayarları geçersiz kılabilir.

İç içe modeller ve karmaşık veriler

Gerçek uygulamalar, karmaşık ve birbiriyle bağlantılı veri yapılarıyla uğraşır. Bir e-ticaret siparişi müşteri bilgileri, gönderim adresleri ve her biri kendi doğrulamasını gerektiren birden çok ürün kalemi içerir:

from typing import List
from datetime import datetime

class Address(BaseModel):
   street: str = Field(min_length=5)
   city: str = Field(min_length=2)
   postal_code: str = Field(pattern=r'^\d{5}(-\d{4})?$')
   country: str = "USA"

class Customer(BaseModel):
   name: str = Field(min_length=1)
   email: EmailStr
   shipping_address: Address
   billing_address: Optional[Address] = None

class OrderItem(BaseModel):
   product_id: int = Field(gt=0)
   quantity: int = Field(gt=0, le=100)
   unit_price: Decimal = Field(gt=0)

class Order(BaseModel):
   order_id: str = Field(pattern=r'^ORD-\d{6}$')
   customer: Customer
   items: List[OrderItem] = Field(min_items=1)
   order_date: datetime = Field(default_factory=datetime.now)

# Karmaşık iç içe veri doğrulaması
order_data = {
   "order_id": "ORD-123456",
   "customer": {
       "name": "John Doe",
       "email": "john@example.com",
       "shipping_address": {
           "street": "123 Main Street",
           "city": "Anytown",
           "postal_code": "12345"
       }
   },
   "items": [
       {"product_id": 1, "quantity": 2, "unit_price": "29.99"},
       {"product_id": 2, "quantity": 1, "unit_price": "149.99"}
   ]
}

order = Order(**order_data)
print(f"Order validated with {len(order.items)} items")

Pydantic iç içe yapıları özyinelemeli olarak doğrular — Customer alanı, kendi Address alanını doğrulayan tam bir Customer nesnesine dönüşür. List[OrderItem] sözdizimi her liste öğesini bir OrderItem olarak doğrularken, Field(min_items=1) envanter sisteminize boş siparişlerin ulaşmasını engeller. default_factory=datetime.now kullanımı, her sipariş örneği için benzersiz zaman damgaları oluşturur.

İsteğe bağlı alanlar ve None işleme

Farklı işlemler farklı veri gereksinimleri ister. Kullanıcı oluşturma tam bilgi talep ederken, güncellemeler kısmi değişiklikleri kabul etmelidir:

from typing import Optional

class UserCreate(BaseModel):
   name: str = Field(min_length=1)
   email: EmailStr
   age: int = Field(ge=13, le=120)
   phone: Optional[str] = Field(None, pattern=r'^\+?1?\d{9,15}$')

class UserUpdate(BaseModel):
   name: Optional[str] = Field(None, min_length=1)
   email: Optional[EmailStr] = None
   age: Optional[int] = Field(None, ge=13, le=120)
   phone: Optional[str] = Field(None, pattern=r'^\+?1?\d{9,15}$')

# Kısmi verilerle PATCH isteği
update_data = {"name": "Jane Smith", "age": 30}
user_update = UserUpdate(**update_data)

# Sadece sağlanan alanları serileştir
patch_data = user_update.model_dump(exclude_none=True)
print(f"Fields to update: {list(patch_data.keys())}")

Serileştirme, Pydantic nesnelerini saklama veya iletim için tekrar sözlüklere ya da JSON metinlerine dönüştürür. model_dump() metodu bu dönüşümü yapar; exclude_none=True ise sağlanmayan alanları kaldırır. Bu desen, istemcilerin sadece değiştirmek istedikleri alanları gönderdiği PATCH istekleri için mükemmeldir ve veritabanınızda yanlışlıkla veri üzerine yazılmasını önler.

Bu temel, uygulamanızın benzersiz iş kurallarını yakalayan özel doğrulama mantığını uygulama mücadelesine hazırlar.

Özel Doğrulama ve Gerçek Dünya Entegrasyonu

Üretim uygulamaları, standart tür kontrol kalıplarına uymayan verileri ele almak anlamına gelir.

Abonelik planlarına göre değişen parola gereksinimlerine sahip bir kullanıcı kayıt formunu veya farklı posta kodu biçimleri olan birden çok ülkeden adres verisi alan bir API’yi düşünün. Bu senaryolar, belirli iş kurallarınızı yakalayan ve web çerçeveleri ile yapılandırma sistemleriyle sorunsuz entegre olan özel doğrulama mantığı gerektirir.

Bu bölüm, pratik özel doğrulama kalıplarını nasıl uygulayacağınızı, Pydantic modellerini otomatik API dokümantasyonu için FastAPI ile nasıl entegre edeceğinizi ve çoğu üretim uygulamasının benimsediği .env dosyası yaklaşımını kullanarak ortam değişkenleriyle uygulama ayarlarını nasıl yöneteceğinizi gösterir.

Alan doğrulayıcıları ve model doğrulaması

İş mantığı veri geçerliliğini belirlediğinde, Pydantic’in @field_validator dekoratörü doğrulama fonksiyonlarınızı bizzat modelin parçasına dönüştürür. Farklı abonelik katmanlarının farklı parola gereksinimleri olduğu bir kullanıcı kayıt sistemini düşünün:

from pydantic import BaseModel, field_validator, Field
import re

class UserRegistration(BaseModel):
   username: str = Field(min_length=3)
   email: EmailStr
   password: str
   subscription_tier: str = Field(pattern=r'^(free|pro|enterprise)$')
  
   @field_validator('password')
   @classmethod
   def validate_password_complexity(cls, password, info):
       tier = info.data.get('subscription_tier', 'free')
      
       if len(password) < 8:
           raise ValueError('Password must be at least 8 characters')
          
       if tier == 'enterprise' and not re.search(r'[A-Z]', password):
           raise ValueError('Enterprise accounts require uppercase letters')
          
       return password

@field_validator dekoratörü, info.data parametresi aracılığıyla diğer alan değerlerine erişim sağlar; böylece birden fazla alana bağlı doğrulama kuralları yazabilirsiniz. Doğrulayıcı, temel tür kontrolü geçildikten sonra çalışır; bu nedenle subscription_tier değerinin izin verilenlerden biri olduğunu varsayabilirsiniz.

Birden fazla alanı kapsayan doğrulamalar için, @model_validator dekoratörü tüm bireysel alanlar doğrulandıktan sonra çalışır:

from datetime import datetime
from pydantic import model_validator

class EventRegistration(BaseModel):
   start_date: datetime
   end_date: datetime
   max_attendees: int = Field(gt=0)
   current_attendees: int = Field(ge=0)
  
   @model_validator(mode='after')
   def validate_event_constraints(self):
       if self.end_date <= self.start_date:
           raise ValueError('Event end date must be after start date')
          
       if self.current_attendees > self.max_attendees:
           raise ValueError('Current attendees cannot exceed maximum')
          
       return self

mode='after' parametresi, doğrulayıcının tamamen oluşturulmuş bir model örneği almasını sağlar; böylece tüm doğrulanmış alanlara erişim gerektiren iş mantığı için idealdir. Doğrulayıcı, başarılı doğrulamayı belirtmek için self döndürmelidir.

FastAPI entegrasyonu

FastAPI’nin Pydantic ile entegrasyonu, otomatik istek doğrulaması ve API dokümantasyonu sağlar. Ana kalıp, farklı işlemler için ayrı modeller oluşturmayı içerir; böylece her yönde hangi verinin aktığını kontrol edebilirsiniz:

from fastapi import FastAPI
from typing import Optional
from datetime import datetime

app = FastAPI()

class UserCreate(BaseModel):
   username: str = Field(min_length=3)
   email: EmailStr
   password: str = Field(min_length=8)

class UserResponse(BaseModel):
   id: int
   username: str
   email: EmailStr
   created_at: datetime
  
@app.post("/users/", response_model=UserResponse)
async def create_user(user: UserCreate):
   # FastAPI istek gövdesini otomatik doğrular
   new_user = {
       "id": 1,
       "username": user.username,
       "email": user.email,
       "created_at": datetime.now()
   }
   return UserResponse(**new_user)

Girdi ve çıktı modelleri arasındaki ayrım çeşitli faydalar sağlar. Girdi modelleri doğrulama kuralları ve zorunlu alanları içerebilirken, çıktı modelleri istemcilere tam olarak hangi verinin gönderileceğini kontrol eder. FastAPI, Pydantic modellerinizden otomatik olarak OpenAPI dokümantasyonu üretir ve geliştiricilerin uç noktaları test etmesine olanak tanıyan etkileşimli API dokümanları oluşturur.

Güncelleme işlemleri için tüm alanların isteğe bağlı olduğu modeller oluşturabilirsiniz:

class UserUpdate(BaseModel):
   username: Optional[str] = Field(None, min_length=3)
   email: Optional[EmailStr] = None

@app.patch("/users/{user_id}")
async def update_user(user_id: int, user_update: UserUpdate):
   # Sadece sağlanan alanları güncelle
   update_data = user_update.model_dump(exclude_unset=True)
   # Buraya veritabanı güncelleme mantığınız gelecek
   return {"message": f"Updated user {user_id}"}

PATCH işlemlerinde exclude_unset=True parametresi, yalnızca açıkça sağlanan alanları güncellemenizi sağlar ve yanlışlıkla üzerine yazmaları önler. Bu desen, istemcilerin kısmi güncellemeler gönderdiği REST API’leri için idealdir.

Ortam değişkenleriyle yapılandırma yönetimi

Üretim uygulamaları, güvenli ve dağıtıma uygun yapılandırma yönetimi gerektirir. Pydantic’in BaseSettings sınıfı ile .env dosyaları birlikte, geliştirme, hazırlık ve üretim ortamlarında çalışan tür güvenli yapılandırma sunar.

Önce, proje kökünüzde bir .env dosyası oluşturun:

# .env dosyası
DATABASE_URL=postgresql://user:password@localhost:5432/myapp
SECRET_KEY=your-secret-key-here
DEBUG=false
ALLOWED_HOSTS=localhost,127.0.0.1,yourdomain.com

Sonra ayar modelinizi tanımlayın:

from pydantic import BaseSettings, Field
from typing import List

class AppSettings(BaseSettings):
   database_url: str = Field(description="Database connection URL")
   secret_key: str = Field(description="Secret key for JWT tokens")
   debug: bool = Field(default=False)
   allowed_hosts: List[str] = Field(default=["localhost"])
  
   class Config:
       env_file = ".env"
       case_sensitive = False

# Ortam değişkenlerinden ve .env dosyasından otomatik ayar yükleme
settings = AppSettings()

BaseSettings sınıfı ortam değişkenlerinden, .env dosyalarından ve komut satırı argümanlarından otomatik okuma yapar. Ortam değişkenleri, .env dosya değerlerine göre önceliklidir; bu da farklı dağıtım ortamlarında ayarları geçersiz kılmayı kolaylaştırır. case_sensitive = False ayarı, ortam değişkeni adlandırmasında esneklik sağlar.

Karmaşık uygulamalar için ayarları mantıksal gruplara bölebilirsiniz:

class DatabaseSettings(BaseSettings):
   url: str = Field(env="DATABASE_URL")
   max_connections: int = Field(default=5, env="DB_MAX_CONNECTIONS")

class AppSettings(BaseSettings):
   secret_key: str
   debug: bool = False
   database: DatabaseSettings = DatabaseSettings()
  
   class Config:
       env_file = ".env"

settings = AppSettings()
# İç içe yapılandırmaya erişim
db_url = settings.database.url

Bu iç içe yaklaşım, ilgili ayarları bir arada tutarken uygulamanızın farklı bileşenleri arasında net bir ayrım sağlar. Her ayar grubu kendi ortam değişkeni öneki ve doğrulama kurallarına sahip olabilir.

.env dosyası yaklaşımı, Heroku, AWS ve Docker gibi dağıtım platformlarıyla uyumludur; bu ortamlarda uygulamaları yapılandırmanın standart yolu ortam değişkenleridir. Uygulamanız, operasyon ekiplerinin beklediği bulut-yerel yapılandırma kalıplarını izlerken tür güvenliği ve doğrulama elde eder.

Bu kalıplar, gerçek dünya karmaşıklığını yöneten sürdürülebilir uygulamalar inşa etmek için temel oluşturur. Pydantic’in doğrulama sistemi, net hata mesajları ve otomatik dokümantasyon sağlayarak belirli gereksinimlerinize uyum sağlar; böylece tüm ekibiniz uygulamanızın beklediği veri yapılarını anlar.

Sonuç

Artık Pydantic’in, doğrulama kodunu elle yazmanın yorucu işinden sizi nasıl kurtarabileceğini gördünüz. Fonksiyonlarınızı isinstance() kontrolleri ve özel hata yönetimiyle doldurmak yerine, veri yapınızı bir kez tanımlayıp gerisini Pydantic’e bırakabilirsiniz.

Daha spesifik Pydantic soruları için aşağıdaki SSS bölümünü mutlaka okuyun. Kapsamlı dokümantasyon ve ileri düzey kalıplar için şu kaynaklardan yararlanabilirsiniz:

SSS

Pydantic doğrulaması uygulamamı yavaşlatır mı?

Pydantic V2, altında Rust ile inşa edilmiştir ve oldukça hızlıdır. Çoğu uygulama için doğrulama ek yükü, önlediği hatalara kıyasla minimum düzeydedir. Performansın kritik olduğu güvenilir veri kaynakları için doğrulamayı atlamak üzere model_construct() kullanabilirsiniz.

Python dataclass’ları yerine Pydantic’i ne zaman kullanmalıyım?

Doğrulamaya ihtiyaç duyduğunuzda, harici veri kaynaklarıyla çalıştığınızda veya API’ler oluşturduğunuzda Pydantic’i kullanın. Girdiye güvendiğiniz basit dahili veri yapıları için dataclass’ları kullanın. Veri kullanıcılar, API’ler veya yapılandırma dosyalarından geldiğinde Pydantic öne çıkar.

Pydantic doğrulama hatalarını üretim uygulamalarında nasıl ele alırım?

ValidationError istisnalarını yakalayın ve yapılandırılmış hata bilgisi almak için .errors() listesini çıkarın. Her hata, kullanıcı dostu hata mesajları sağlamanıza veya ayrıntılı hata ayıklama bilgilerini kaydetmenize yardımcı olan loc, msg ve type alanlarını içerir.

Pydantic’i mevcut koda her şeyi bozmadan ekleyebilir miyim?

Evet! Harici veri giriş noktalarını (API istekleri, dosya ayrıştırma) Pydantic modelleriyle sarmalayarak başlayın. Dahili veri yapılarınızı kademeli olarak dönüştürebilirsiniz. Pydantic mevcut kodla yan yana çalışır ve tüm kod tabanınızı bir anda değiştirmenizi gerektirmez.

Pydantic’e başlarken yapılan en yaygın hata nedir?

Tür zorlama mantığını anlamamak. Pydantic varsayılan olarak uyumlu türleri dönüştürür (örneğin metin "123" tamsayı 123’e). Sıkı tür kontrolüne ihtiyacınız varsa, otomatik dönüşümleri engellemek için Field(strict=True) kullanın veya model yapılandırmanızda sıkı modu etkinleştirin.


Bex Tuychiev's photo
Author
Bex Tuychiev
LinkedIn

2 yılı aşkın deneyime sahip bir veri bilimi içerik üreticisiyim ve Medium'da en büyük takipçi kitlelerinden birine sahibim. Yapay zeka ve makine öğrenimi üzerine, biraz da alaycı bir üslupla, ayrıntılı yazılar yazmayı seviyorum; çünkü bu konuları biraz olsun sıkıcılıktan çıkarmak gerekiyor. 130'dan fazla makale ve bir DataCamp kursu hazırladım; bir diğeri de yolda. İçeriklerim 5 milyondan fazla kişi tarafından görüntülendi; bunların 20 bini Medium ve LinkedIn'de takipçim oldu. 

Konular

DataCamp ile veri bilimi öğrenin!

Kurs

Python'da Yazılım Mühendisliği İlkeleri

4 sa
66.4K
Modülerlik, belgeleme ve otomatik testlerle veri bilimi sorunlarını daha hızlı ve güvenilir şekilde çözün.
Ayrıntıları GörRight Arrow
Kursa Başla
Devamını GörRight Arrow