Python Web 生態的分水嶺

2018 年是 Python web 的分水嶺。FastAPI 出現之前,Django 和 Flask 是唯二的主流選擇。之後格局變了:

  • Django:全功能框架,CRUD 快,生態大,但 async 是事後加的
  • FastAPI:async-first,Pydantic 原生整合,OpenAPI 自動生成,型別安全極佳
  • Flask:輕量 minimal,但 async 支援差,新專案選它的理由越來越少
  • Starlette:FastAPI 的底層,低層次 ASGI toolkit

理解這四個的定位,你就知道新專案該選哪個。


Django:Batteries-Included 的王者

Django(2005)的設計哲學是「一個框架給你全部」:ORM、Admin panel、authentication、form handling、template engine。你不需要選哪個 ORM、哪個 auth library——Django 都幫你決定了。

# Django model — ORM 直接 built-in
class User(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField(unique=True)
    created_at = models.DateTimeField(auto_now_add=True)
 
    class Meta:
        db_table = 'users'
 
# Django REST Framework view
class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.select_related('profile').all()
    serializer_class = UserSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DjangoFilterBackend, SearchFilter]
    search_fields = ['name', 'email']
 
# 一行設定 → 完整 CRUD + filtering + pagination
router.register(r'users', UserViewSet)

Django Admin 是 Django 最強的殺手鐧——幾行設定就有一個功能完整的後台管理介面,對 MVP 和內部工具極其有用。

Django 的 async 痛點

Django 的 ORM 是從同步設計出發的,async 是 3.1 版(2020)才加入,但很多操作還是要用 sync_to_async() 包裝:

# Django async view + ORM 的痛苦
async def user_detail(request, id):
    # User.objects.get() 是同步的,需要包裝
    user = await sync_to_async(User.objects.get)(pk=id)
    # 或 Django 4.1 的 async ORM
    user = await User.objects.aget(pk=id)  # async get
    return JsonResponse({'name': user.name})

比較 FastAPI 同樣的操作:

# FastAPI + SQLAlchemy async
async def user_detail(id: int, db: AsyncSession = Depends(get_db)):
    result = await db.execute(select(User).where(User.id == id))
    user = result.scalar_one_or_none()
    return user

Django 適合:標準 CRUD 為主、需要 Admin panel、不需要高並發的系統;MVP 快速開發。


FastAPI:2026 年 Python API 開發的最佳選擇

FastAPI(2018)解決的是 Flask / Django 的幾個具體問題:

問題一:request body 沒有型別安全

Flask / Django:body 是 dict,你自己解析,自己驗證,TypeScript 的 any 問題 Python 版。

FastAPI:宣告 Pydantic schema 就完成了。

from pydantic import BaseModel, EmailStr, Field
 
class UserCreate(BaseModel):
    name: str = Field(min_length=1, max_length=100)
    email: EmailStr
    age: int = Field(ge=0, le=150)
 
@app.post("/users", status_code=201)
async def create_user(user: UserCreate):
    # user.name, user.email, user.age 全部已驗證且有型別
    return await user_service.create(user)

問題二:API 文件要手寫

Flask / Django REST Framework:Swagger 要靠插件,還要手寫 docstring 或 schema。

FastAPI:OpenAPI 文件自動生成,/docs 直接可用,不需要任何設定:

@app.post("/users",
    status_code=201,
    summary="Create a new user",
    response_model=UserResponse,
    responses={400: {"model": ErrorResponse}},
)
async def create_user(user: UserCreate):
    ...
# /docs 自動有這個 endpoint 的完整文件,包含 schema、example、response codes

問題三:async 是事後加的

Flask / Django 的 async 支援都有歷史包袱。FastAPI 從第一天就是 async-first。

FastAPI 的缺點

  • 沒有內建 admin panel(需要 Piccolo Admin、SQLAdmin 等第三方)
  • 沒有內建 ORM(需要自己選 SQLAlchemy、Tortoise ORM 等)
  • 比 Django 要自己搭的東西更多

FastAPI 適合:I/O 密集的高 QPS API;需要 OpenAPI 文件;重視型別安全;新 Python 後端專案的首選。


Flask:輕量,但 2026 年的理由越來越少

Flask(2010)和 Express 一樣:minimal,只給你路由和 middleware,其他都自己來。

from flask import Flask, request, jsonify
 
app = Flask(__name__)
 
@app.route('/users', methods=['POST'])
def create_user():
    data = request.get_json()  # ← dict,沒有驗證,沒有型別
    name = data.get('name')
    email = data.get('email')
    # 自己驗證、自己格式化...
    return jsonify({'id': 1, 'name': name}), 201

Flask 的問題是:它的 async 支援比 FastAPI 差很多,生態也在 FastAPI 出現後大量遷移。2026 年如果你需要 minimal Python web framework,FastAPI 幾乎在所有維度都優於 Flask。

Flask 還在的場景:維護既有 Flask 應用;極輕量的一次性腳本 API(不值得設 FastAPI 的 Pydantic 架構)。


Starlette:FastAPI 的底層

Starlette 是 FastAPI 的底層 ASGI framework,比 FastAPI 更低層次——不包含 Pydantic 整合,但提供路由、middleware、WebSocket、background tasks 的基礎設施。

# 直接用 Starlette(很少這樣做)
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route
 
async def user_list(request):
    users = await user_service.find_all()
    return JSONResponse([u.dict() for u in users])
 
app = Starlette(routes=[
    Route('/users', user_list),
])

直接用 Starlette 的場景:你需要比 FastAPI 更低層次的控制,或你在做 ASGI middleware / plugin 開發。一般 API 開發直接用 FastAPI。


選擇決策

需要 Admin panel 和完整 batteries-included?
  → Django + DRF

API-first、型別安全、async-first、OpenAPI 自動文件?
  → FastAPI

維護既有 Flask 專案?
  → Flask(不要新起一個 Flask 專案了)

低層次 ASGI middleware / plugin 開發?
  → Starlette

延伸閱讀