⏱️4 min read · 805 words
Pydantic v2 হল 2026 সালে সবচেয়ে গুরুত্বপূর্ণ Python লাইব্রেরি আপগ্রেড। Rust এ পুনরায় লেখা (pydantic-core এর মাধ্যমে), এটি একটি ক্লিনার API, কঠোর মোড এবং মডেল ভ্যালিডেটর সহ v1 থেকে 5-50x দ্রুত। এই নির্দেশিকা ব্যবহারিক উদাহরণ সহ প্রতিটি Pydantic v2 বৈশিষ্ট্য কভার করে।
📋 Table of Contents
ইনস্টলেশন এবং মাইগ্রেশন
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
কর্মক্ষমতা: v1 বনাম v2
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
2026 সালে Pydantic v2 হল Python এর জন্য বৈধতা মান। মরিচা কোর উল্লেখযোগ্য কর্মক্ষমতা লাভ প্রদান করে। ফিল্ড ভ্যালিডেটররা ডাটা ইস্যু তাড়াতাড়ি ধরতে পারে, মডেল ভ্যালিডেটররা ক্রস-ফিল্ডের সীমাবদ্ধতাগুলিকে প্রয়োগ করে এবং কঠোর মোড নীরব জবরদস্তি বাগগুলি দূর করে। bump-pydantic ব্যবহার করে v1 থেকে মাইগ্রেট করুন — এটি স্বয়ংক্রিয়ভাবে 90% পরিবর্তন পরিচালনা করে।
🔗 Share this article
✍️ Leave a Comment