آنچه در این مقاله میخوانید [پنهانسازی]
Pydantic ابزاری قدرتمند برای اعتبارسنجی و سریال سازی داده ها در پایتون است که بر پایه تایپ هینت ها کار می کند. انعطاف پذیری پایتون در مدیریت انواع داده ها اگرچه سرعت توسعه را بالا می برد، اما هنگام دریافت ورودی های نامعتبر از APIها، فایل های پیکربندی یا فرم های کاربری می تواند منجر به خطاهای زمان اجرا شود. هدف Pydantic این است که با استفاده از تایپ هینت ها، ساختار دقیق داده های مورد انتظار را تعریف کند و قوانین را به صورت خودکار اعمال نماید. در این راهنما با ساخت مدل ها، اعمال محدودیت ها، نوشتن اعتبارسنج های سفارشی، مدیریت ساختارهای تو در تو و سریال سازی آشنا می شوید تا در پروژه های واقعی از آن استفاده کنید.
سرفصل های مقاله
نصب و آغاز کار
برای شروع کار با Pydantic باید بسته آن را نصب کنید. این کار با دستور زیر انجام می شود:
pip install pydantic
پس از نصب می توانید کدهای مثال را قدم به قدم اجرا کنید و با قابلیت های این کتابخانه آشنا شوید.
مدل های پایه
برخلاف روش های سنتی که نیاز به بررسی های دستی و دستورات if متعدد دارند، Pydantic مستقیما با تایپ هینت ها کار می کند و آنها را به منطق اعتبارسنجی تبدیل می نماید. زمانی که داده با مشخصات تعریف شده همخوانی نداشته باشد، به جای خطاهای مبهم، پیام های خطای واضح و قابل فهم دریافت خواهید کرد. مدل ها از BaseModel ارث بری می کنند و ساختار داده را با تایپ هینت مشخص می سازند:
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
email: str
user = User(name="Alice", age="25", email="alice@example.com")
print(user.age)
print(type(user.age))
خروجی:
25
<class 'int'>
در این مثال مقدار “25” به طور خودکار به عدد صحیح تبدیل می شود. اگر تبدیل ممکن نباشد، خطای اعتبارسنجی شفاف دریافت خواهید کرد. این ویژگی هنگام کار با JSON یا فرم ها بسیار مفید است.
فیلدهای اختیاری و مقادیر پیش فرض
در پروژه های واقعی برخی فیلدها ممکن است اجباری نباشند. با استفاده از Optional و تعریف مقدار پیش فرض می توانید این نیاز را برطرف کنید. همچنین Field امکان اعمال محدودیت هایی مانند حداقل طول را فراهم می کند:
from pydantic import BaseModel, Field
from typing import Optional
class Product(BaseModel):
name: str
price: float
description: Optional[str] = None
in_stock: bool = True
category: str = Field(default="general", min_length=1)
product1 = Product(name="Widget", price=9.99)
product2 = Product(name="Gadget", price=15.50, description="Useful tool")
در این کد description می تواند رشته یا None باشد. فیلدهایی که مقدار پیش فرض دارند در ورودی الزامی نیستند. با Field شرط حداقل یک کاراکتر برای category اعمال شده تا داده های ناقص به صورت کنترل شده مدیریت شوند.
اعتبارسنج های سفارشی
گاهی اوقات نیاز به قواعدی فراتر از بررسی نوع داده دارید. با اعتبارسنج های سفارشی می توانید منطق دلخواه خود را پیاده سازی کنید و حتی داده را نرمال سازی نمایید:
from pydantic import BaseModel, field_validator
import re
class Account(BaseModel):
username: str
email: str
password: str
@field_validator('username')
def validate_username(cls, v):
if len(v) < 3:
raise ValueError('Username must be at least 3 characters')
if not v.isalnum():
raise ValueError('Username must be alphanumeric')
return v.lower()
@field_validator('email')
def validate_email(cls, v):
pattern = r'^[\w\.-]+@[\w\.-]+\.\w+$'
if not re.match(pattern, v):
raise ValueError('Invalid email format')
return v
@field_validator('password')
def validate_password(cls, v):
if len(v) < 8:
raise ValueError('Password must be at least 8 characters')
return v
account = Account(
username="JohnDoe123",
email="john@example.com",
password="secretpass123"
)
اعتبارسنج ها در هنگام ساخت شیء اجرا می شوند. آنها می توانند مقدار را تغییر دهند یا با پیام های واضح آن را رد کنند. ترتیب تعریف همان ترتیب اجراست و در صورت نیاز می توان به مقادیر اعتبارسنجی شده قبلی دسترسی داشت.
مدل های تو در تو و ساختارهای پیچیده
در کاربردهای واقعی داده ها معمولا ساختار سلسله مراتبی دارند. Pydantic اعتبارسنجی داده های تو در تو را ساده می کند:
from pydantic import BaseModel, field_validator
from typing import List, Optional
from datetime import datetime
class Address(BaseModel):
street: str
city: str
state: str
zip_code: str
@field_validator('zip_code')
def validate_zip(cls, v):
if not v.isdigit() or len(v) != 5:
raise ValueError('ZIP code must be 5 digits')
return v
class Contact(BaseModel):
name: str
phone: str
email: Optional[str] = None
class Company(BaseModel):
name: str
founded: datetime
address: Address
contacts: List[Contact]
employee_count: int
is_public: bool = False
company_data = {
"name": "Tech Corp",
"founded": "2020-01-15T10:00:00",
"address": {
"street": "123 Main St",
"city": "San Francisco",
"state": "CA",
"zip_code": "94105"
},
"contacts": [
{"name": "John Smith", "phone": "555-0123"},
{"name": "Jane Doe", "phone": "555-0456", "email": "jane@techcorp.com"}
],
"employee_count": 150
}
company = Company(**company_data)
در این مثال تمام ساختار به صورت بازگشتی اعتبارسنجی می شود. address بر اساس قواعد Address بررسی می شود، هر عضو contacts باید با مدل Contact سازگار باشد و رشته تاریخ به datetime تبدیل می گردد. اگر بخشی نامعتبر باشد، خطا با اشاره دقیق به محل مشکل نمایش داده می شود.
کار با API و JSON
داده های API معمولا با انواع مختلط، فرمت های زمانی متفاوت و فیلدهای اختیاری دریافت می شوند. Pydantic این چالش ها را به خوبی مدیریت می کند:
from pydantic import BaseModel, Field, field_validator
from typing import Union, Optional
from datetime import datetime
import json
class APIResponse(BaseModel):
status: str
message: Optional[str] = None
data: Optional[dict] = None
timestamp: datetime = Field(default_factory=datetime.now)
class UserProfile(BaseModel):
id: int
username: str
full_name: Optional[str] = None
age: Optional[int] = Field(None, ge=0, le=150)
created_at: Union[datetime, str]
is_verified: bool = False
@field_validator('created_at', mode='before')
def parse_created_at(cls, v):
if isinstance(v, str):
try:
return datetime.fromisoformat(v.replace('Z', '+00:00'))
except ValueError:
raise ValueError('Invalid datetime format')
return v
api_json = '''
{
"status": "success",
"data": {
"id": 123,
"username": "alice_dev",
"full_name": "Alice Johnson",
"age": "28",
"created_at": "2023-01-15T10:30:00Z",
"is_verified": true
}
}
'''
response_data = json.loads(api_json)
api_response = APIResponse(**response_data)
if api_response.data:
user = UserProfile(**api_response.data)
print(f"User {user.username} created at {user.created_at}")
خروجی:
User alice_dev created at 2023-01-15 10:30:00+00:00
در این کد از mode=’before’ استفاده شده تا تبدیل قبل از تایپ کست انجام شود. همچنین با Field محدودیت سن تعریف شده تا ورودی های غیرمعقول پذیرفته نشوند.
مدیریت خطا و ValidationError
زمانی که ورودی نامعتبر است، Pydantic جزئیات خطا را به صورت ساختاریافته ارائه می دهد:
from pydantic import BaseModel, ValidationError, field_validator
from typing import List
class Order(BaseModel):
order_id: int
customer_email: str
items: List[str]
total: float
@field_validator('total')
def positive_total(cls, v):
if v <= 0:
raise ValueError('Total must be positive')
return v
bad_data = {
"order_id": "not_a_number",
"customer_email": "invalid_email",
"items": "should_be_list",
"total": -10.50
}
try:
order = Order(**bad_data)
except ValidationError as e:
print("Validation errors:")
for error in e.errors():
field = error['loc'][0]
message = error['msg']
print(f" {field}: {message}")
print("\nJSON errors:")
print(e.json(indent=2))
این ساختار خطا شامل نام فیلد، نوع خطا و پیام قابل فهم است. بنابراین چه برای نمایش به کاربر و چه برای ثبت در لاگ، اطلاعات کافی در دسترس خواهید داشت.
سریال سازی و خروجی گرفتن
تبدیل مدل ها به دیکشنری یا JSON بسیار ساده است و می توانید فیلدها را شامل یا حذف کنید:
from pydantic import BaseModel
from datetime import datetime
class Event(BaseModel):
name: str
date: datetime
attendees: int
is_public: bool = True
event = Event(
name="Python Meetup",
date=datetime(2024, 3, 15, 18, 30),
attendees=45
)
event_dict = event.model_dump()
print(event_dict)
event_json = event.model_dump_json()
print(event_json)
public_data = event.model_dump(exclude={'attendees'})
print(public_data)
formatted_json = event.model_dump_json(indent=2)
print(formatted_json)
با model_dump و model_dump_json می توانید نمایش های متفاوتی از یک داده بسازید. برای مثال مخفی کردن فیلدهای حساس یا تولید JSON قالب بندی شده برای پاسخ API. این انعطاف باعث می شود یک مدل واحد نیازهای متنوع لایه های مختلف برنامه را پوشش دهد.
جمع بندی
Pydantic فرآیند اعتبارسنجی داده را از یک کار پرخطا و زمان بر به رویکردی اعلامی، تمیز و خودکار تبدیل می کند. با تکیه بر تایپ هینت ها همزمان خوانایی کد حفظ می شود و از طرفی تضمین زمان اجرا برای ساختار داده فراهم می آید. در این راهنما دیدید چگونه مدل های پایه بسازید، فیلدهای اختیاری و پیش فرض تعریف کنید، اعتبارسنج های سفارشی بنویسید، داده های تو در تو را مدیریت کنید و در نهایت خروجی های متناسب با نیاز هر سناریو تولید نمایید. اگر در پروژه های واقعی کار با ورودی های غیرقابل اعتماد، JSON خام یا پاسخ های ناهمگون API چالش شما بوده است، با Pydantic می توانید خطاها را زودتر شناسایی کنید، پیام های روشن تری به کاربر ارائه دهید و از تکرار کار جلوگیری نمایید. تمرین با همین الگوها بهترین راه برای تسلط است و هرجا که نیاز به قواعد دقیق تری داشتید کافی است یک اعتبارسنج جدید اضافه کنید یا از پیکربندی های پیشرفته استفاده نمایید.






