Pydantic فراتر از اعتبارسنجی

بررسی کتابخانه محبوب Pydantic

Pydantic: فراتر از اعتبارسنجی

بررسی ۱۰ ویژگی قدرتمند کتابخانه‌ای که مدیریت داده‌ها در پایتون مدرن را متحول کرده است.
(بر اساس Pydantic نسخه ۲)

در دنیای واقعی، داده‌ها کثیف و غیرقابل اعتماد هستند. نوشتن دستی کد برای بررسی و تمیز کردن این داده‌ها کابوس است. Pydantic با استفاده از Type Hintهای استاندارد پایتون، این فرآیند را به یک تجربه لذت‌بخش، سریع و ایمن تبدیل می‌کند. در ادامه ۱۰ دلیل اصلی برای استفاده از آن را بررسی می‌کنیم.

فلسفه اصلی: استفاده از Type Hintها به عنوان Schema

برخلاف بسیاری از کتابخانه‌ها که نیاز به یادگیری زبان تعریف اسکمای جدید دارند، Pydantic از همان سینتکس استاندارد پایتون (که از نسخه 3.6 معرفی شد) استفاده می‌کند. شما یک کلاس از `BaseModel` ارث‌بری می‌کنید و متغیرها را با تایپشان تعریف می‌کنید. همین!

main.py
from pydantic import BaseModel

# تعریف مدل با استفاده از تایپ‌های استاندارد
class User(BaseModel):
    id: int
    username: str
    is_active: bool = True # مقدار پیش‌فرض

# استفاده از مدل
user = User(id=123, username="ali_reza")
print(user.username) # دسترسی آسان با دات‌نوتیشن

تجزیه و تبدیل هوشمند (Smart Parsing & Coercion)

شعار Pydantic این است: "Parse, don't validate". این یعنی به جای اینکه فقط خطا بگیرد، سعی می‌کند داده ورودی را به تایپ هدف تبدیل کند. اگر رشته "123" را به فیلدی که int است بدهید، Pydantic آن را به عدد تبدیل می‌کند. این ویژگی در کار با APIها و فرم‌های وب که همه چیز رشته است، حیاتی است.

parsing.py
class Product(BaseModel):
    price: float
    available: bool

# داده‌های خام از یک درخواست HTTP (همه رشته هستند)
raw_data = {"price": "99.50", "available": "yes"}

product = Product(**raw_data)

print(product.price)      # خروجی: 99.5 (float)
print(product.available)  # خروجی: True (bool)
# Pydantic مقادیری مثل "yes", "on", "1" را به True تبدیل می‌کند.

سرعت بی‌نظیر با هسته Rust (در نسخه 2)

در نسخه دوم، هسته اصلی Pydantic با زبان Rust بازنویسی شد (پروژه‌ای به نام pydantic-core). این تغییر باعث افزایش سرعت چشمگیر (بین 5 تا 50 برابر سریع‌تر از نسخه 1) شده است. این یعنی پردازش داده‌ها در مقیاس بالا دیگر گلوگاه برنامه شما نخواهد بود.

نکته: این افزایش سرعت باعث شده Pydantic به یکی از سریع‌ترین کتابخانه‌های اعتبارسنجی داده در کل اکوسیستم پایتون تبدیل شود.

مدیریت ساختارهای تو در تو و پیچیده

داده‌های واقعی معمولاً ساختار درختی دارند (مثلاً یک فاکتور که شامل لیستی از آیتم‌هاست). Pydantic به راحتی با استفاده از مدل‌های دیگر به عنوان تایپ، این ساختارها را مدیریت، اعتبارسنجی و تبدیل می‌کند.

nested.py
from typing import List

class Address(BaseModel):
    city: str

class UserWithAddress(BaseModel):
    name: str
    # استفاده از یک مدل دیگر به عنوان تایپ
    address: Address 
    # لیستی از مدل‌ها
    tags: List[str]

data = {
    "name": "Sara",
    "address": {"city": "Tehran"}, # دیکشنری تو در تو
    "tags": ["admin", "123"]
}

user = UserWithAddress(**data)
print(user.address.city) # دسترسی عمیق: Tehran

پشتیبانی عالی از تایپ‌های استاندارد پایتون

Pydantic به صورت ذاتی از تایپ‌های پیچیده‌تر کتابخانه استاندارد پایتون مانند datetime, date, UUID, Enum و Path پشتیبانی می‌کند و رشته‌های ورودی را به این آبجکت‌های قدرتمند تبدیل می‌کند.

std_types.py
from datetime import datetime
from uuid import UUID
from enum import Enum

class Status(Enum):
    ACTIVE = "active"
    INACTIVE = "inactive"

class LogEntry(BaseModel):
    id: UUID
    timestamp: datetime
    status: Status

raw_log = {
    "id": "123e4567-e89b-12d3-a456-426614174000", # رشته UUID
    "timestamp": "2023-10-27T15:30:00Z",          # رشته ISO 8601
    "status": "active"                             # رشته Enum
}

log = LogEntry(**raw_log)
# حالا log.timestamp واقعاً یک آبجکت datetime است
print(log.timestamp.year) # 2023

تایپ‌های تخصصی (ایمیل، URL و ...)

برای اعتبارسنجی‌های رایج، نیازی به نوشتن Regex نیست. Pydantic تایپ‌های آماده‌ای مثل EmailStr, HttpUrl, IPvAnyAddress و غیره دارد که صحت فرمت داده را تضمین می‌کنند.

نکته: دقت شود که برای اعتبارسنجی این بخش باید یک بار دستور pip install pydantic[email] را اجرا نمایید.
special_types.py
from pydantic import BaseModel, EmailStr, HttpUrl, ValidationError

class Contact(BaseModel):
    email: EmailStr
    website: HttpUrl

try:
    Contact(email="invalid-email", website="htps://typo.com")
except ValidationError as e:
    print(e.json())
    # خطای دقیق برای هر دو فیلد ایمیل و وب‌سایت برمی‌گرداند

اعتبارسنجی‌های سفارشی (Custom Validators)

وقتی تایپ‌های پیش‌فرض کافی نیستند، می‌توانید با استفاده از دکوریتور @field_validator منطق خود را اعمال کنید. این توابع می‌توانند داده را تغییر دهند (نرمال‌سازی) یا خطا برگردانند.

custom_validator.py
from pydantic import BaseModel, field_validator

class Account(BaseModel):
    username: str

    # اعمال قانون خاص روی فیلد username
    @field_validator('username')
    @classmethod
    def must_be_alphanumeric(cls, v: str) -> str:
        if not v.isalnum():
            raise ValueError('نام کاربری فقط باید شامل حروف و اعداد باشد')
        return v.lower() # نرمال‌سازی به حروف کوچک

acc = Account(username="Ali123")
print(acc.username) # ali123

سریال‌سازی انعطاف‌پذیر (خروجی گرفتن)

تبدیل آبجکت‌های پایتون به JSON (مخصوصاً وقتی شامل datetime هستند) همیشه دردسر دارد. Pydantic با متدهای model_dump() (برای دیکشنری) و model_dump_json() (برای رشته JSON) این کار را به سادگی و با قابلیت‌های کنترلی بالا (مثل حذف فیلدهای خاص) انجام می‌دهد.

export.py
from datetime import datetime
class Event(BaseModel):
    title: str
    time: datetime
    secret_code: str

event = Event(title="Meeting", time=datetime.now(), secret_code="XYZ")

# خروجی JSON استاندارد، با حذف فیلد secret_code
json_output = event.model_dump_json(exclude={'secret_code'})
print(json_output)
# Output: {"title":"Meeting", "time":"2023-10-27T..."}

مدیریت نام‌های مستعار (Aliases) و ادغام سیستم‌ها

در پایتون نام استاندارد snake_case است، اما در جاوااسکریپت (فرانت‌اند) camelCase رایج است. Pydantic با استفاده از Aliasها پل ارتباطی بین این دو دنیا می‌شود، بدون اینکه کد پایتون شما زشت شود.

aliases.py
from pydantic import BaseModel, Field

class UserProfile(BaseModel):
    # ورودی JSON دارای کلید firstName است، اما در پایتون first_name استفاده می‌شود
    first_name: str = Field(alias="firstName")
    last_name: str = Field(alias="lastName")

# داده از فرانت‌اند
js_data = {"firstName": "Kaveh", "lastName": "Tehrani"}
user = UserProfile(**js_data)

print(user.first_name) # استفاده از نام پایتونی

# هنگام خروجی گرفتن هم می‌توان از alias استفاده کرد
print(user.model_dump_json(by_alias=True))
# {"firstName":"Kaveh", "lastName":"Tehrani"}

مدیریت تنظیمات پروژه (Settings Management)

با استفاده از پکیج جانبی pydantic-settings، می‌توانید تنظیمات برنامه را مستقیماً از متغیرهای محیطی (Environment Variables) یا فایل‌های .env بخوانید، اعتبارسنجی کنید و به تایپ‌های صحیح (مثل int برای پورت یا bool برای حالت دیباگ) تبدیل کنید. این بهترین روش برای پیاده‌سازی اپلیکیشن‌های ۱۲ فاکتوری است.

config.py (requires pydantic-settings)
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    db_host: str = "localhost" # مقدار پیش‌فرض
    db_port: int # الزامی (حتما باید عدد باشد)
    api_key: str
    debug: bool = False

    model_config = SettingsConfigDict(env_file =
        "my_file.env") # خواندن خودکار از فایل .env

# اگر در محیط، DB_PORT="5432" و DEBUG="true" باشد:
settings = Settings()
print(settings.db_port) # 5432 (int)
print(settings.debug)   # True (bool)

مهدوی

برنامه نویس پایتون و جنگو

هنوز هیچ دیدگاهی ثبت نشده است!

به جامعه دانشجویان ما بپیوندید!

به جامعه دانشجویان ما بپیوندید و از جدیدترین دوره‌ها و مقالات ما باخبر شوید