🌐 Detecting your location…
📢 Advertisement — Configure AdSense in Appearance → Customize → AdSense Settings

الدليل الكامل لـ Python Pydantic v2 2026: التحقق من الصحة والتسلسل وFastAPI

⏱️4 min read  ·  799 words

يعد Pydantic v2 أهم ترقية لمكتبة Python في عام 2026. تمت إعادة كتابته في Rust (عبر pydantic-core)، وهو أسرع بمقدار 5-50 مرة من الإصدار 1 مع واجهة برمجة تطبيقات أكثر نظافة ووضعًا صارمًا وأدوات التحقق من صحة النماذج. يغطي هذا الدليل كل ميزات Pydantic v2 مع أمثلة عملية.

التثبيت والهجرة

pip install pydantic>=2.0

# Auto-migrate from v1
pip install bump-pydantic
bump-pydantic .

# Key changes from v1:
# - class Config -> model_config = ConfigDict(...)
# - @validator -> @field_validator + @model_validator
# - .dict() -> .model_dump()
# - .json() -> .model_dump_json()
# - __fields__ -> model_fields

النماذج الأساسية

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

class User(BaseModel):
    model_config = ConfigDict(
        str_strip_whitespace=True,     # strip whitespace from strings
        str_min_length=1,              # no empty strings
        validate_assignment=True,      # validate on attribute assignment
        populate_by_name=True,         # allow field name OR alias
        use_enum_values=True,          # store enum.value not enum
    )

    id: int
    name: str = Field(min_length=2, max_length=50)
    email: EmailStr
    age: Optional[int] = Field(default=None, ge=13, le=120)
    role: str = Field(default="user", pattern=r"^(user|admin|moderator)$")
    created_at: datetime = Field(default_factory=datetime.utcnow)
    tags: list[str] = Field(default_factory=list, max_length=10)

# Create
user = User(id=1, name="Alice Chen", email="alice@example.com", age=30)
print(user.model_dump())
print(user.model_dump_json(indent=2))

# Partial update
updated = user.model_copy(update={"name": "Alice Smith"})

# From dict
user2 = User.model_validate({"id": 2, "name": "Bob", "email": "bob@example.com"})

# From JSON string
user3 = User.model_validate_json('{"id": 3, "name": "Carol", "email": "carol@example.com"}')

المدققون

from pydantic import BaseModel, field_validator, model_validator, Field
import re

class PasswordChange(BaseModel):
    current_password: str
    new_password: str = Field(min_length=8)
    confirm_password: str

    @field_validator("new_password")
    @classmethod
    def password_strength(cls, v: str) -> str:
        if not re.search(r"[A-Z]", v):
            raise ValueError("Must contain uppercase letter")
        if not re.search(r"[0-9]", v):
            raise ValueError("Must contain digit")
        if not re.search(r"[!@#$%^&*]", v):
            raise ValueError("Must contain special character")
        return v

    @model_validator(mode="after")  # runs after all field validators
    def passwords_match(self) -> "PasswordChange":
        if self.new_password != self.confirm_password:
            raise ValueError("Passwords do not match")
        if self.new_password == self.current_password:
            raise ValueError("New password must differ from current")
        return self

# Validate and get all errors at once
from pydantic import ValidationError

try:
    PasswordChange(
        current_password="old123",
        new_password="short",
        confirm_password="different"
    )
except ValidationError as e:
    print(e.error_count(), "errors")
    for error in e.errors():
        print(f"  {error['loc']}: {error['msg']}")

الوضع الصارم

from pydantic import BaseModel, ConfigDict

class StrictUser(BaseModel):
    model_config = ConfigDict(strict=True)  # no coercion!

    id: int
    name: str
    active: bool

# Without strict: "1" coerced to int, "true" to bool
# With strict: exact types required
try:
    StrictUser(id="1", name="Alice", active="true")  # raises!
except Exception as e:
    print(e)

# Strict per-field
from pydantic import Strict
from typing import Annotated

class PartiallyStrict(BaseModel):
    id: Annotated[int, Strict()]  # strict for this field only
    name: str  # coercion allowed

الأسماء المستعارة والتسلسل

from pydantic import BaseModel, Field, AliasPath
from pydantic.functional_serializers import model_serializer

class APIResponse(BaseModel):
    # Accept camelCase from API, use snake_case internally
    model_config = ConfigDict(populate_by_name=True)

    user_id: int = Field(alias="userId")
    first_name: str = Field(alias="firstName")
    last_name: str = Field(alias="lastName")
    created_at: str = Field(alias="createdAt")

    # Nested alias path
    city: str = Field(validation_alias=AliasPath("address", "city"))

# Parse camelCase JSON
data = {
    "userId": 1,
    "firstName": "Alice",
    "lastName": "Chen",
    "createdAt": "2026-01-15",
    "address": {"city": "Sydney", "country": "AU"}
}
response = APIResponse.model_validate(data)
print(response.user_id, response.first_name, response.city)

# Serialize back to camelCase
print(response.model_dump(by_alias=True))  # {"userId": 1, ...}

Pydantic + FastAPI (نمط 2026)

from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field, ConfigDict
from typing import Annotated
from datetime import datetime

app = FastAPI()

class UserCreate(BaseModel):
    name: Annotated[str, Field(min_length=2, max_length=50)]
    email: Annotated[str, Field(pattern=r"^[^@]+@[^@]+\.[^@]+$")]
    password: Annotated[str, Field(min_length=8, exclude=True)]  # exclude from response

class UserResponse(BaseModel):
    model_config = ConfigDict(from_attributes=True)  # allows ORM model input

    id: int
    name: str
    email: str
    created_at: datetime

    @classmethod
    def from_orm_with_extras(cls, obj, **extras) -> "UserResponse":
        return cls.model_validate({**obj.__dict__, **extras})

@app.post("/users", response_model=UserResponse, status_code=201)
async def create_user(data: UserCreate) -> UserResponse:
    # data.password available but won't appear in response
    user = await db.users.create({
        "name": data.name,
        "email": data.email,
        "password_hash": hash_password(data.password)
    })
    return UserResponse.model_validate(user)

# Automatic OpenAPI docs show the schema
# Pydantic v2 JSON Schema generation is much better than v1

الأداء: الإصدار 1 مقابل الإصدار 2

import timeit
from pydantic import BaseModel

class BenchModel(BaseModel):
    id: int
    name: str
    email: str
    score: float

data = {"id": 1, "name": "Alice", "email": "alice@example.com", "score": 9.5}

n = 100_000
t = timeit.timeit(lambda: BenchModel(**data), number=n)
print(f"Pydantic v2: {t:.2f}s for {n:,} validations ({n/t:,.0f}/sec)")
# Typical: ~2-5x faster than v1, up to 50x for complex nested models

Pydantic v2 في عام 2026 هو معيار التحقق من صحة Python. يوفر قلب Rust مكاسب كبيرة في الأداء. تكتشف أدوات التحقق من الصحة الميدانية مشكلات البيانات مبكرًا، وتفرض أدوات التحقق من صحة النماذج قيودًا عبر الحقول، ويزيل الوضع الصارم أخطاء الإكراه الصامتة. قم بالترحيل من الإصدار الأول باستخدام Bump-Pydantic — فهو يتعامل مع 90% من التغييرات تلقائيًا.

✍️ Leave a Comment

Your email address will not be published. Required fields are marked *

🌐 Read in:🇬🇧 English🇩🇪 Deutsch🇧🇷 Português🇸🇦 العربية🇮🇳 हिन्दी🇧🇩 বাংলা