Kurs
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:
- Yanlış Python ortamı: Sanal ortamınızın etkin olduğundan emin olun
- Birden fazla Python sürümü: Pydantic’i kuran Python sürümünü kullandığınızı doğrulayın
- 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:
UsersınıfınızBaseModel’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: strsözdizimi,name’in metin olması gerektiğini;age: intise 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ğunuzpydantic[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 = Truegibi alanların varsayılan değerleri vardır. Bir kullanıcı oluştururken bu alanları sağlamazsanız, Pydantic varsayılanları kullanır.created_atiçin= Nonebu 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:
- Resmi dokümantasyon:
- Pydantic Dokümantasyonu — Örnekler ve en iyi uygulamalarla tam başvuru
- Pydantic Geçiş Rehberi — Sürümler arasında yükseltme için temel okuma
- FastAPI Dokümantasyonu — Pydantic’in otomatik API dokümantasyonunu nasıl güçlendirdiğini öğrenin
- İlgili DataCamp öğrenme kaynakları:
- Python’da Model Doğrulama — scikit-learn ile doğrulama tekniklerine derin dalış
- FastAPI’ye Giriş — Pydantic entegrasyonuyla üretim API’leri oluşturun
- Python’da API’lere Giriş — Harici API’lerle çalışma ve JSON veri doğrulama
- Orta Düzey Python — Pydantic kullanımını tamamlayan Python temellerine hâkim olun
- Python’da Nesne Yönelimli Programlama — Pydantic modellerini anlamak için temel oluşturun
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.
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.
