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

Validation

ใน Express คุณต้องเลือก validation library (Joi, Zod, class-validator) แล้วเชื่อมต่อเอง ใน FastAPI validation ไม่ใช่ตัวเลือก แต่รันอัตโนมัติสำหรับทุก request ทันทีที่คุณประกาศ typed parameter ถ้า validation ล้มเหลว FastAPI จะส่งคืน 422 Unprocessable Entity พร้อม structured error body ก่อนที่ handler function จะทำงาน

pydantic.Field เทียบเท่ากับ .min(), .max(), .regex() ของ Zod หรือ decorator @IsEmail(), @Min() ของ NestJS

TypeScript
// Zod
const CreateItemSchema = z.object({
name: z.string().min(1).max(100),
price: z.number().positive().max(99999),
quantity: z.number().int().min(0).default(1),
email: z.string().email().optional(),
slug: z.string().regex(/^[a-z0-9-]+$/).optional(),
});
// class-validator (NestJS)
export class CreateItemDto {
@IsString() @MinLength(1) @MaxLength(100) name: string;
@IsNumber() @IsPositive() @Max(99999) price: number;
@IsInt() @Min(0) @IsOptional() quantity?: number = 1;
@IsEmail() @IsOptional() email?: string;
}
Python
# Pydantic with Field constraints
from pydantic import BaseModel, Field, EmailStr
from typing import Optional
class CreateItem(BaseModel):
name: str = Field(min_length=1, max_length=100)
price: float = Field(gt=0, le=99999)
quantity: int = Field(default=1, ge=0)
email: Optional[EmailStr] = None # ต้องการ: pip install pydantic[email]
slug: Optional[str] = Field(
default=None,
pattern=r"^[a-z0-9-]+$"
)

ตาราง Field constraint:

Field kwarg ใน Pydanticความหมายเทียบเท่าใน Zod
gt=0มากกว่า.positive()
ge=0มากกว่าหรือเท่ากับ.min(0)
lt=100น้อยกว่า.max(99)
le=100น้อยกว่าหรือเท่ากับ.max(100)
min_length=1ความยาวขั้นต่ำ.min(1)
max_length=100ความยาวสูงสุด.max(100)
pattern=r"..."regex.regex(...)

เมื่อ validation ล้มเหลว FastAPI จะส่ง structured JSON body อัตโนมัติ ไม่ต้องเพิ่ม middleware และไม่ต้องเขียน try/catch

TypeScript
// Zod การเชื่อมต่อ manual
app.post('/items', (req, res) => {
const result = CreateItemSchema.safeParse(req.body);
if (!result.success) {
return res.status(422).json({ errors: result.error.flatten() });
}
// ...
});
Python
# FastAPI — 422 อัตโนมัติ ไม่ต้องเขียน code
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class CreateItem(BaseModel):
name: str = Field(min_length=1)
price: float = Field(gt=0)
@app.post("/items")
async def create_item(item: CreateItem):
return item # ถึงตรงนี้ได้ก็ผ่าน validation แล้ว
# POST /items {} คืนค่า:
# {
# "detail": [
# {"loc": ["body","name"], "msg":"Field required", "type":"missing"},
# {"loc": ["body","price"],"msg":"Field required", "type":"missing"}
# ]
# }

รันที่เครื่องตัวเองด้วย FastAPI สำหรับ validation จริง snippet ด้านล่างแสดง logic เดียวกันโดยใช้ stdlib เท่านั้น

from dataclasses import dataclass
from typing import Optional
import re
@dataclass
class ValidationError:
field: str
message: str
def validate_item(data: dict) -> list:
errors = []
# name: required, 1-100 chars
name = data.get("name", "")
if not name:
errors.append(ValidationError("name", "Field required"))
elif len(name) > 100:
errors.append(ValidationError("name", "max_length=100"))
# price: required, must be > 0
price = data.get("price")
if price is None:
errors.append(ValidationError("price", "Field required"))
elif not isinstance(price, (int, float)) or price <= 0:
errors.append(ValidationError("price", "gt=0"))
# quantity: optional, must be >= 0 integer
qty = data.get("quantity", 1)
if not isinstance(qty, int) or qty < 0:
errors.append(ValidationError("quantity", "ge=0"))
# slug: optional regex
slug = data.get("slug")
if slug and not re.match(r"^[a-z0-9-]+$", slug):
errors.append(ValidationError("slug", "pattern mismatch"))
return errors
tests = [
{"name": "Widget", "price": 9.99, "quantity": 2, "slug": "widget-pro"},
{},
{"name": "X", "price": -5, "quantity": -1, "slug": "BAD SLUG"},
]
for t in tests:
errs = validate_item(t)
if errs:
print(f"INVALID {t}")
for e in errs:
print(f" [{e.field}] {e.message}")
else:
print(f"VALID {t}")
FastAPI ส่ง HTTP status ใดอัตโนมัติเมื่อ Pydantic validation ล้มเหลว?
Pydantic Field kwarg ใดกำหนด "มากกว่าศูนย์"?
Pydantic v2 equivalent ของ Zod's .refine() สำหรับ custom field logic คืออะไร?
ใน FastAPI ต้องเขียน try/catch หรือ middleware เพื่อส่งคืน 422 เมื่อ input ไม่ถูกต้องหรือไม่?