ข้ามไปยังเนื้อหา

Pydantic Models

ใน TypeScript คุณอธิบายรูปร่าง request body ด้วย interface หรือ Zod schema ใน FastAPI คุณอธิบายด้วย subclass ของ Pydantic BaseModel ส่ง class นั้นเป็น type hint บน argument ของ route function และ FastAPI จะ parse และ validate request body อัตโนมัติ

TypeScript
// TypeScript — Zod schema + inferred type
import { z } from 'zod';
const CreateItemSchema = z.object({
name: z.string().min(1),
price: z.number().positive(),
inStock: z.boolean().default(true),
tags: z.array(z.string()).default([]),
});
type CreateItem = z.infer<typeof CreateItemSchema>;
// NestJS DTO with class-validator
export class CreateItemDto {
@IsString() @MinLength(1) name: string;
@IsNumber() @IsPositive() price: number;
@IsBoolean() @IsOptional() inStock?: boolean = true;
}
Python
# FastAPI — Pydantic BaseModel
from pydantic import BaseModel
from typing import Optional, List
class CreateItem(BaseModel):
name: str
price: float
in_stock: bool = True
tags: List[str] = []
# ใช้ใน route — FastAPI parse + validate อัตโนมัติ
from fastapi import FastAPI
app = FastAPI()
@app.post("/items", status_code=201)
async def create_item(item: CreateItem):
return item # Pydantic serialize กลับเป็น JSON

Pydantic models รวมกันได้อย่างเป็นธรรมชาติ ฝัง model หนึ่งไว้ใน model อื่นเหมือน nested Zod objects

TypeScript
// Zod nested object
const AddressSchema = z.object({
street: z.string(),
city: z.string(),
zip: z.string().length(5),
});
const UserSchema = z.object({
name: z.string(),
address: AddressSchema,
});
Python
# Pydantic nested models
from pydantic import BaseModel
class Address(BaseModel):
street: str
city: str
zip_code: str
class User(BaseModel):
name: str
address: Address
# FastAPI จะ parse nested JSON นี้อัตโนมัติ:
# { "name": "Alice", "address": { "street": "1 Main St", ... } }

รูปแบบที่พบบ่อยคือมี model แยกกันสำหรับ input (สิ่งที่ client ส่งมา) และ output (สิ่งที่คุณส่งกลับ) Pydantic ทำให้ compose ง่ายมาก

TypeScript
// TypeScript — แยก input / output types
interface CreateItemDto { name: string; price: number; }
interface ItemResponse { id: number; name: string; price: number; createdAt: string; }
Python
# Pydantic — แยก input / output models
from pydantic import BaseModel
from datetime import datetime
class CreateItem(BaseModel): # Request body
name: str
price: float
class ItemResponse(BaseModel): # Response shape
id: int
name: str
price: float
created_at: datetime
# Route ใช้ response_model= เพื่อ filter + serialize
from fastapi import FastAPI
app = FastAPI()
@app.post("/items", response_model=ItemResponse, status_code=201)
async def create_item(item: CreateItem):
# ปกติจะบันทึกลง DB แล้ว return row
return ItemResponse(id=1, name=item.name, price=item.price,
created_at=datetime.utcnow())

Pydantic ไม่สามารถรันใน browser ได้ dataclasses จาก standard library ให้รูปร่างเดียวกัน (typed fields, defaults, auto __init__) โดยไม่มี validation เพื่อให้สำรวจแนวคิดได้:

from dataclasses import dataclass, field, asdict
from typing import Optional, List
import json
@dataclass
class CreateItem:
name: str
price: float
in_stock: bool = True
tags: List[str] = field(default_factory=list)
description: Optional[str] = None
# สร้าง instance — รู้สึกเหมือน BaseModel(...)
item = CreateItem(name="Widget", price=9.99, tags=["sale", "new"])
print("item:", item)
# Serialize เป็น dict (เหมือน .model_dump())
data = asdict(item)
print("dict :", data)
# Serialize เป็น JSON
print("json :", json.dumps(data, indent=2))
# Nested dataclass
@dataclass
class OrderLine:
item: CreateItem
quantity: int
line = OrderLine(item=item, quantity=3)
print("\nnested:", asdict(line))
Pydantic equivalent ของ Zod schema หรือ TypeScript interface สำหรับ request body คืออะไร?
ใน Pydantic v2 method ใด serialize model instance เป็น Python dict?
FastAPI รู้ได้อย่างไรว่าควร parse request body เป็น Pydantic model แทนที่จะถือว่าเป็น query param?