FastAPI เป็นเว็บเฟรมเวิร์กสำหรับ Python ที่ได้รับความนิยมเพิ่มขึ้นอย่างรวดเร็วในช่วง 2-3 ปีที่ผ่านมา และในปี 2026 ก็กลายเป็นหนึ่งในตัวเลือกอันดับต้นๆ สำหรับการสร้าง REST API ด้วยภาษา Python ด้วยความเร็วในการประมวลผลที่ใกล้เคียง Node.js และ Go รองรับ async/await อย่างเต็มรูปแบบ พร้อมระบบ type hints ที่ช่วยให้โค้ดปลอดภัยและดูแลรักษาง่าย
บทความนี้จะพาคุณไปตั้งแต่เริ่มต้นจนถึงการ deploy ครอบคลุมทุกหัวข้อสำคัญที่นักพัฒนาควรรู้ ไม่ว่าจะเป็น path parameters, request body ด้วย Pydantic, การเชื่อมต่อฐานข้อมูลด้วย SQLAlchemy, ระบบ authentication ด้วย JWT และแนวปฏิบัติที่ดีที่สุดสำหรับปี 2026
FastAPI คืออะไร?
FastAPI เป็น modern web framework สำหรับ Python 3.7+ ที่สร้างขึ้นโดย Sebastián Ramírez โดยใช้ประโยชน์จาก Python type hints อย่างเต็มที่ ชื่อ "Fast" มาจาก 2 ความหมาย คือ เร็วในการรัน (performance) และเร็วในการเขียนโค้ด (developer productivity)
สิ่งที่ทำให้ FastAPI โดดเด่นเหนือเฟรมเวิร์กอื่นคือ:
- ประสิทธิภาพสูง — ใช้ Starlette เป็น core และ Uvicorn เป็น ASGI server ทำให้เร็วเทียบเท่า Node.js และ Go
- Type Safety — ใช้ Python type hints + Pydantic ในการ validate ข้อมูลอัตโนมัติ ลด bug ได้มาก
- Auto Documentation — สร้าง Swagger UI และ ReDoc ให้อัตโนมัติจากโค้ดโดยไม่ต้องเขียนเอง
- Async Support — รองรับ async/await natively ทำให้จัดการ concurrent requests ได้ดีเยี่ยม
- Standards-based — ยึดตามมาตรฐาน OpenAPI (Swagger) และ JSON Schema
การติดตั้ง FastAPI
การเริ่มต้นกับ FastAPI ง่ายมาก เพียงติดตั้ง 2 แพ็กเกจหลัก ได้แก่ fastapi ตัวเฟรมเวิร์ก และ uvicorn ตัว ASGI server สำหรับรันแอปพลิเคชัน
สร้าง Virtual Environment
# สร้างโฟลเดอร์โปรเจกต์
mkdir fastapi-project && cd fastapi-project
# สร้าง virtual environment
python -m venv venv
# activate (Linux/Mac)
source venv/bin/activate
# activate (Windows)
venv\Scripts\activate
ติดตั้ง FastAPI และ Uvicorn
# ติดตั้งแบบเต็ม (แนะนำ)
pip install "fastapi[standard]"
# หรือติดตั้งแยก
pip install fastapi uvicorn[standard]
# ตรวจสอบเวอร์ชัน
python -c "import fastapi; print(fastapi.__version__)"
fastapi[standard] จะติดตั้ง dependencies ที่จำเป็นทั้งหมดรวมถึง uvicorn, pydantic, python-multipart และ jinja2
สร้าง API ตัวแรก (Hello World)
มาเริ่มสร้าง API ตัวแรกกัน สร้างไฟล์ main.py ดังนี้:
from fastapi import FastAPI
app = FastAPI(
title="My First API",
description="API ตัวแรกของฉัน",
version="1.0.0"
)
@app.get("/")
async def root():
return {"message": "สวัสดี FastAPI!", "status": "ok"}
@app.get("/health")
async def health_check():
return {"status": "healthy", "version": "1.0.0"}
รันเซิร์ฟเวอร์ด้วยคำสั่ง:
uvicorn main:app --reload --host 0.0.0.0 --port 8000
เปิดเบราว์เซอร์ไปที่ http://localhost:8000 จะเห็น JSON response และไปที่ http://localhost:8000/docs จะเห็น Swagger UI ที่สร้างอัตโนมัติ พร้อมให้ทดสอบ API ได้เลย
Path Parameters และ Query Parameters
FastAPI ทำให้การรับ parameters จาก URL ง่ายและปลอดภัยด้วย type hints
Path Parameters
from fastapi import FastAPI, HTTPException
app = FastAPI()
# Database จำลอง
users_db = {
1: {"id": 1, "name": "สมชาย", "email": "somchai@example.com"},
2: {"id": 2, "name": "สมหญิง", "email": "somying@example.com"}
}
@app.get("/users/{user_id}")
async def get_user(user_id: int):
if user_id not in users_db:
raise HTTPException(status_code=404, detail="ไม่พบผู้ใช้")
return users_db[user_id]
@app.get("/users/{user_id}/posts/{post_id}")
async def get_user_post(user_id: int, post_id: int):
return {"user_id": user_id, "post_id": post_id}
FastAPI จะแปลง user_id เป็น int ให้อัตโนมัติ ถ้าส่งค่าที่ไม่ใช่ตัวเลขมา จะได้ 422 Validation Error พร้อมข้อความอธิบายที่ชัดเจน
Query Parameters
from typing import Optional
@app.get("/products")
async def get_products(
category: Optional[str] = None,
min_price: float = 0,
max_price: float = 999999,
page: int = 1,
limit: int = 20
):
return {
"category": category,
"price_range": [min_price, max_price],
"page": page,
"limit": limit
}
เรียกใช้ได้เช่น /products?category=electronics&min_price=100&page=2 ค่าที่ไม่ส่งมาจะใช้ค่า default ที่กำหนดไว้
Request Body กับ Pydantic Models
Pydantic เป็นหัวใจสำคัญของ FastAPI ทำหน้าที่ validate และ serialize ข้อมูลที่รับเข้ามา ทำให้ API ปลอดภัยจากข้อมูลที่ไม่ถูกต้องโดยอัตโนมัติ
from pydantic import BaseModel, Field, EmailStr
from typing import Optional
from datetime import datetime
class UserCreate(BaseModel):
name: str = Field(..., min_length=2, max_length=100,
description="ชื่อผู้ใช้")
email: EmailStr = Field(..., description="อีเมล")
age: int = Field(..., ge=13, le=120,
description="อายุ (13-120)")
bio: Optional[str] = Field(None, max_length=500)
class UserResponse(BaseModel):
id: int
name: str
email: str
age: int
bio: Optional[str]
created_at: datetime
class Config:
from_attributes = True # Pydantic v2
@app.post("/users", response_model=UserResponse,
status_code=201)
async def create_user(user: UserCreate):
# Pydantic validate ข้อมูลให้อัตโนมัติ
new_user = {
"id": 3,
"name": user.name,
"email": user.email,
"age": user.age,
"bio": user.bio,
"created_at": datetime.now()
}
return new_user
Pydantic v2 ที่ใช้ใน FastAPI 0.100+ มีการปรับปรุงประสิทธิภาพอย่างมาก เร็วขึ้น 5-50 เท่าเมื่อเทียบกับ v1 เนื่องจาก core ถูกเขียนใหม่ด้วย Rust
Nested Models และ Validation ขั้นสูง
from pydantic import BaseModel, field_validator
from typing import List
class Address(BaseModel):
street: str
city: str
province: str
postal_code: str
@field_validator("postal_code")
@classmethod
def validate_postal(cls, v):
if not v.isdigit() or len(v) != 5:
raise ValueError("รหัสไปรษณีย์ต้องเป็นตัวเลข 5 หลัก")
return v
class OrderItem(BaseModel):
product_id: int
quantity: int = Field(ge=1, le=100)
price: float = Field(gt=0)
class Order(BaseModel):
customer_name: str
shipping_address: Address
items: List[OrderItem] = Field(min_length=1)
@property
def total(self) -> float:
return sum(i.price * i.quantity for i in self.items)
@app.post("/orders")
async def create_order(order: Order):
return {
"message": "สร้างออเดอร์สำเร็จ",
"total": order.total,
"items_count": len(order.items)
}
เชื่อมต่อฐานข้อมูลด้วย SQLAlchemy
ในโปรเจกต์จริง คุณจะต้องเชื่อมต่อกับฐานข้อมูล SQLAlchemy เป็น ORM ยอดนิยมที่ทำงานร่วมกับ FastAPI ได้อย่างดีเยี่ยม รองรับทั้ง PostgreSQL, MySQL, SQLite และอื่นๆ
โครงสร้างโปรเจกต์
fastapi-project/
├── main.py
├── database.py
├── models.py
├── schemas.py
├── crud.py
├── routers/
│ ├── users.py
│ └── products.py
├── requirements.txt
└── .env
ตั้งค่า Database Connection
# database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
SQLALCHEMY_DATABASE_URL = "postgresql://user:password@localhost/mydb"
# สำหรับ SQLite ใช้:
# SQLALCHEMY_DATABASE_URL = "sqlite:///./app.db"
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False,
bind=engine)
Base = declarative_base()
# Dependency สำหรับ inject DB session
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
สร้าง Models
# models.py
from sqlalchemy import Column, Integer, String, Float,
DateTime, ForeignKey
from sqlalchemy.orm import relationship
from datetime import datetime
from database import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
name = Column(String(100), nullable=False)
email = Column(String(255), unique=True, index=True)
hashed_password = Column(String(255))
created_at = Column(DateTime, default=datetime.utcnow)
posts = relationship("Post", back_populates="author")
class Post(Base):
__tablename__ = "posts"
id = Column(Integer, primary_key=True, index=True)
title = Column(String(200), nullable=False)
content = Column(String, nullable=False)
author_id = Column(Integer, ForeignKey("users.id"))
created_at = Column(DateTime, default=datetime.utcnow)
author = relationship("User", back_populates="posts")
CRUD Operations
# crud.py
from sqlalchemy.orm import Session
from models import User, Post
from schemas import UserCreate, PostCreate
from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"])
def create_user(db: Session, user: UserCreate):
hashed = pwd_context.hash(user.password)
db_user = User(
name=user.name,
email=user.email,
hashed_password=hashed
)
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user
def get_users(db: Session, skip: int = 0, limit: int = 20):
return db.query(User).offset(skip).limit(limit).all()
def get_user_by_email(db: Session, email: str):
return db.query(User).filter(User.email == email).first()
ใช้ Dependency Injection ใน Router
# routers/users.py
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from database import get_db
import crud, schemas
router = APIRouter(prefix="/api/v1/users", tags=["users"])
@router.post("/", response_model=schemas.UserResponse,
status_code=201)
def create_user(user: schemas.UserCreate,
db: Session = Depends(get_db)):
existing = crud.get_user_by_email(db, user.email)
if existing:
raise HTTPException(400, "อีเมลนี้ถูกใช้แล้ว")
return crud.create_user(db, user)
@router.get("/", response_model=list[schemas.UserResponse])
def list_users(skip: int = 0, limit: int = 20,
db: Session = Depends(get_db)):
return crud.get_users(db, skip, limit)
ระบบ Authentication ด้วย JWT
การทำ authentication เป็นสิ่งจำเป็นสำหรับ API ที่ใช้งานจริง FastAPI มี security utilities ที่ช่วยให้ implement OAuth2 + JWT ได้ง่าย
# auth.py
from datetime import datetime, timedelta
from typing import Optional
from jose import JWTError, jwt
from fastapi import Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
SECRET_KEY = "your-secret-key-change-in-production"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
def create_access_token(data: dict,
expires_delta: Optional[timedelta] = None):
to_encode = data.copy()
expire = datetime.utcnow() + (
expires_delta or timedelta(minutes=15)
)
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
async def get_current_user(
token: str = Depends(oauth2_scheme),
db: Session = Depends(get_db)
):
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="ไม่สามารถยืนยันตัวตนได้",
headers={"WWW-Authenticate": "Bearer"}
)
try:
payload = jwt.decode(token, SECRET_KEY,
algorithms=[ALGORITHM])
email: str = payload.get("sub")
if email is None:
raise credentials_exception
except JWTError:
raise credentials_exception
user = crud.get_user_by_email(db, email)
if user is None:
raise credentials_exception
return user
# Login endpoint
@app.post("/token")
async def login(form_data: OAuth2PasswordRequestForm = Depends(),
db: Session = Depends(get_db)):
user = authenticate_user(db, form_data.username,
form_data.password)
if not user:
raise HTTPException(400, "อีเมลหรือรหัสผ่านไม่ถูกต้อง")
token = create_access_token(data={"sub": user.email})
return {"access_token": token, "token_type": "bearer"}
# Protected endpoint
@app.get("/me")
async def read_me(current_user = Depends(get_current_user)):
return current_user
openssl rand -hex 32 สร้างได้ และเก็บใน environment variable เสมอ
Middleware และ Error Handling
Middleware ช่วยให้คุณเพิ่มฟังก์ชันที่ทำงานทุกครั้งที่มี request เข้ามา เช่น logging, CORS, rate limiting
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
import time
import logging
app = FastAPI()
# CORS Middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["https://yourfrontend.com"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"]
)
# Custom Logging Middleware
@app.middleware("http")
async def log_requests(request: Request, call_next):
start = time.time()
response = await call_next(request)
duration = time.time() - start
logging.info(
f"{request.method} {request.url.path} "
f"{response.status_code} {duration:.3f}s"
)
return response
# Global Exception Handler
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc):
logging.error(f"Unhandled error: {exc}")
return JSONResponse(
status_code=500,
content={"detail": "เกิดข้อผิดพลาดภายในเซิร์ฟเวอร์"}
)
Background Tasks และ WebSocket
FastAPI รองรับ background tasks สำหรับงานที่ใช้เวลานานโดยไม่ต้องให้ client รอ และ WebSocket สำหรับการสื่อสารแบบ real-time
Background Tasks
from fastapi import BackgroundTasks
def send_email_notification(email: str, message: str):
# ส่งอีเมล (ใช้เวลานาน)
import smtplib
# ... logic ส่งอีเมล ...
@app.post("/subscribe")
async def subscribe(
email: str,
background_tasks: BackgroundTasks
):
background_tasks.add_task(
send_email_notification,
email,
"ยินดีต้อนรับสู่ระบบ!"
)
return {"message": "สมัครสำเร็จ อีเมลยืนยันกำลังส่ง"}
WebSocket
from fastapi import WebSocket, WebSocketDisconnect
connected_clients: list[WebSocket] = []
@app.websocket("/ws/chat")
async def websocket_chat(websocket: WebSocket):
await websocket.accept()
connected_clients.append(websocket)
try:
while True:
data = await websocket.receive_text()
# Broadcast ไปทุก client
for client in connected_clients:
await client.send_text(
f"ข้อความใหม่: {data}"
)
except WebSocketDisconnect:
connected_clients.remove(websocket)
Testing API ด้วย pytest
การเขียน test เป็นสิ่งสำคัญสำหรับ API ที่ใช้งานจริง FastAPI มี TestClient ที่ทำให้เขียน test ได้ง่าย
# test_main.py
from fastapi.testclient import TestClient
from main import app
client = TestClient(app)
def test_read_root():
response = client.get("/")
assert response.status_code == 200
assert "message" in response.json()
def test_create_user():
response = client.post("/users", json={
"name": "ทดสอบ",
"email": "test@example.com",
"age": 25
})
assert response.status_code == 201
data = response.json()
assert data["name"] == "ทดสอบ"
def test_create_user_invalid_email():
response = client.post("/users", json={
"name": "ทดสอบ",
"email": "invalid-email",
"age": 25
})
assert response.status_code == 422
def test_get_user_not_found():
response = client.get("/users/99999")
assert response.status_code == 404
# รัน: pytest test_main.py -v
การ Deploy FastAPI สู่ Production
เมื่อพัฒนาเสร็จแล้ว ขั้นตอนสุดท้ายคือการ deploy สู่ production มีหลายทางเลือก:
วิธีที่ 1: Docker (แนะนำ)
# Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0",
"--port", "8000", "--workers", "4"]
# docker-compose.yml
services:
api:
build: .
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://user:pass@db/mydb
- SECRET_KEY=${SECRET_KEY}
depends_on:
- db
restart: unless-stopped
db:
image: postgres:16
volumes:
- pgdata:/var/lib/postgresql/data
environment:
- POSTGRES_DB=mydb
- POSTGRES_USER=user
- POSTGRES_PASSWORD=pass
volumes:
pgdata:
วิธีที่ 2: Gunicorn + Uvicorn Workers
# สำหรับ production บน Linux
pip install gunicorn
gunicorn main:app \
--workers 4 \
--worker-class uvicorn.workers.UvicornWorker \
--bind 0.0.0.0:8000 \
--access-logfile - \
--error-logfile -
วิธีที่ 3: Cloud Platforms
FastAPI deploy ได้ง่ายบนหลาย platform:
| Platform | วิธี Deploy | ราคาเริ่มต้น |
|---|---|---|
| Railway | เชื่อม GitHub repo อัตโนมัติ | $5/เดือน |
| Render | เชื่อม GitHub + Dockerfile | ฟรี (limited) |
| Fly.io | CLI deploy + Dockerfile | ฟรี (limited) |
| AWS Lambda | Mangum adapter | Pay-per-use |
| Google Cloud Run | Container-based | Pay-per-use |
| DigitalOcean App | เชื่อม GitHub | $5/เดือน |
เปรียบเทียบ FastAPI vs Flask vs Django
เลือกเฟรมเวิร์กที่เหมาะกับงานของคุณ:
| คุณสมบัติ | FastAPI | Flask | Django |
|---|---|---|---|
| ประเภท | ASGI (async) | WSGI (sync) | WSGI (sync) |
| Performance | สูงมาก | ปานกลาง | ปานกลาง |
| Learning Curve | ง่าย-ปานกลาง | ง่าย | ปานกลาง-ยาก |
| Auto Docs | มี (Swagger + ReDoc) | ไม่มี (ต้องเพิ่ม) | ไม่มี (ต้องเพิ่ม) |
| Data Validation | Pydantic (built-in) | ไม่มี | Forms/Serializers |
| ORM | ไม่มี (ใช้ SQLAlchemy) | ไม่มี (ใช้ SQLAlchemy) | Django ORM |
| Admin Panel | ไม่มี | ไม่มี | มี (built-in) |
| Async Support | Native | จำกัด | จำกัด (ASGI) |
| เหมาะกับ | API, Microservices | API ขนาดเล็ก, Prototype | Full-stack web app |
สรุป: ถ้าสร้าง REST API โดยเฉพาะ ให้เลือก FastAPI ถ้าต้องการ full-stack web app พร้อม admin panel ให้เลือก Django ส่วน Flask เหมาะกับ prototype ขนาดเล็กหรือเมื่อต้องการความยืดหยุ่นสูงสุด
Best Practices สำหรับ FastAPI ในปี 2026
แนวปฏิบัติที่ดีที่จะช่วยให้โปรเจกต์ของคุณดูแลรักษาได้ง่ายและ scale ได้ดี:
1. จัดโครงสร้างโปรเจกต์ให้เป็นระบบ
ใช้ APIRouter แบ่ง endpoint ตามหมวดหมู่ แยก models, schemas, crud ออกจากกัน อย่าเขียนทุกอย่างใน main.py ไฟล์เดียว
2. ใช้ Pydantic Settings สำหรับ Configuration
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
database_url: str
secret_key: str
debug: bool = False
api_prefix: str = "/api/v1"
class Config:
env_file = ".env"
settings = Settings()
3. ใช้ Alembic สำหรับ Database Migration
# ติดตั้งและเริ่มต้น
pip install alembic
alembic init alembic
# สร้าง migration
alembic revision --autogenerate -m "add users table"
# รัน migration
alembic upgrade head
4. ใช้ Dependency Injection อย่างเต็มที่
FastAPI มีระบบ DI ที่ทรงพลัง ใช้มันสำหรับ database sessions, authentication, permissions, caching และ shared resources ทั้งหมด
5. เขียน Test เสมอ
ใช้ pytest + httpx สำหรับ async testing ตั้ง CI/CD ให้รัน test อัตโนมัติทุกครั้งที่ push โค้ด
6. ใช้ Logging ที่เหมาะสม
ใช้ structlog หรือ loguru แทน print() สำหรับ production ตั้ง log level ให้เหมาะสม (INFO สำหรับ production, DEBUG สำหรับ development)
7. Rate Limiting และ Security
# ใช้ slowapi สำหรับ rate limiting
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
@app.get("/api/data")
@limiter.limit("100/minute")
async def get_data(request: Request):
return {"data": "limited"}
8. API Versioning
ใช้ prefix ใน URL เช่น /api/v1/ และ /api/v2/ เพื่อให้สามารถอัปเดต API ได้โดยไม่ break client เดิม
9. ใช้ async อย่างถูกต้อง
ถ้าฟังก์ชันไม่มี I/O operation ที่เป็น async (เช่น database query, HTTP request) ไม่จำเป็นต้องใช้ async def ใช้ def ธรรมดาก็ได้ FastAPI จะรันใน thread pool ให้อัตโนมัติ
10. Documentation ที่ดี
เพิ่ม description, examples, tags ใน endpoint เพื่อให้ Swagger UI แสดงข้อมูลที่ครบถ้วน ทีมงานจะขอบคุณ
สรุป
FastAPI เป็นเฟรมเวิร์กที่ยอดเยี่ยมสำหรับการสร้าง REST API ด้วย Python ในปี 2026 ด้วยประสิทธิภาพสูง ระบบ type safety ที่แข็งแกร่ง auto documentation ที่สะดวก และ ecosystem ที่สมบูรณ์ ไม่ว่าจะเป็นมือใหม่หรือมือเก๋า FastAPI ก็เป็นทางเลือกที่คุ้มค่าแก่การเรียนรู้และใช้งาน
สิ่งที่เราได้เรียนรู้ในบทความนี้:
- FastAPI คืออะไรและทำไมถึงได้รับความนิยม
- การติดตั้งและสร้าง API ตัวแรก
- Path Parameters, Query Parameters และ Request Body
- Pydantic Models สำหรับ data validation
- เชื่อมต่อฐานข้อมูลด้วย SQLAlchemy
- ระบบ Authentication ด้วย JWT
- Middleware, Error Handling, Background Tasks
- WebSocket สำหรับ real-time communication
- Testing ด้วย pytest
- การ Deploy สู่ production
- เปรียบเทียบกับ Flask และ Django
- Best Practices 10 ข้อสำหรับปี 2026
เริ่มต้นเขียน FastAPI วันนี้ แล้วคุณจะพบว่าการสร้าง API ด้วย Python ไม่เคยง่ายและสนุกขนาดนี้มาก่อน
