Backend Architecture¶
Backend sử dụng FastAPI với kiến trúc Layered Architecture — tách biệt rõ ràng giữa routing, business logic, data access, và validation.
Layered Architecture¶
graph TD
A["🌐 API Layer<br/>api/courses.py"] --> B["💼 Service Layer<br/>services/"]
B --> C["📋 Model Layer<br/>models/"]
C --> D["🗄️ Database<br/>core/database.py"]
A --> E["✅ Schema Layer<br/>schemas/"]
A --> F["📦 Storage Service<br/>services/storage_service.py"] | Layer | Thư mục | Trách nhiệm |
|---|---|---|
| API | api/ | Route handlers, nhận request, trả response |
| Service | services/ | Business logic, xử lý nghiệp vụ |
| Model | models/ | SQLAlchemy ORM — định nghĩa bảng database |
| Schema | schemas/ | Pydantic — validate input/output |
| Core | core/ | Config, database connection |
| Utils | utils/ | Helper functions (slugify, etc.) |
Entry Point — main.py¶
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from api.courses import router as courses_router
from core.config import settings
app = FastAPI(title="Cloudflare Courses API")
# CORS origins đọc từ biến môi trường
origins = [o.strip() for o in settings.CORS_ORIGINS.split(",")]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
app.include_router(courses_router)
CORS
CORS_ORIGINS là chuỗi phân cách bởi dấu phẩy. Ví dụ: http://localhost:3000,https://chienle.dev.
Configuration — core/config.py¶
Sử dụng Pydantic Settings để validate biến môi trường khi startup:
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
DATABASE_URL: str # PostgreSQL connection string
R2_ENDPOINT: str # Cloudflare R2 endpoint
R2_KEY: str # R2 Access Key
R2_SECRET: str # R2 Secret Key
R2_BUCKET: str # R2 Bucket name
CDN_BASE: str # Public CDN URL
CORS_ORIGINS: str = "*" # Allowed origins (mặc định: all)
class Config:
env_file = ".env"
extra = "ignore"
Thiếu biến = Crash
Tất cả các biến (trừ CORS_ORIGINS) đều bắt buộc. Thiếu bất kỳ biến nào → Pydantic raise ValidationError → FastAPI crash ngay khi khởi động.
Database Connection — core/database.py¶
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, declarative_base
engine = create_engine(
settings.DATABASE_URL,
pool_pre_ping=True, # Auto-reconnect nếu connection bị drop
pool_size=5, # Connection pool size
max_overflow=10 # Extra connections khi pool đầy
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
def get_db():
"""Dependency injection — tạo DB session cho mỗi request."""
db = SessionLocal()
try:
yield db
finally:
db.close()
Thêm module mới¶
Khi cần thêm entity mới (ví dụ: User):
- Tạo model:
models/user.py - Tạo schema:
schemas/user.py - Tạo service:
services/user_service.py - Tạo router:
api/users.py - Register router trong
main.py:app.include_router(users_router) - Tạo migration:
alembic revision --autogenerate -m "Add users table" - Chạy migration:
alembic upgrade head