
当 Flask 还在纠结装饰器嵌套时,FastAPI 已经用类型注解把 API 写成了自文档。它不是"又一个 Python 框架",而是 Python 生态里目前写 API 最高效的方式。
对比维度 | Flask / Django | FastAPI |
|---|---|---|
开发速度 | 中等,需手动写文档 | 极快,类型注解自动生成 OpenAPI 文档 |
性能 | 中等(WSGI) | 极高(ASGI + Starlette,benchmark 级别接近 Node.js/Go) |
数据校验 | 需第三方库(marshmallow 等) | 原生集成 Pydantic,类型即校验 |
异步支持 | Flask 2.0+ 部分支持 | 原生异步,天然适配高并发场景 |
**学习曲线 | Flask 低,Django 高 | 中等偏低,Python 基础 + 类型注解即可上手 |
一句话总结:如果你用 Python 写 REST API,2025 年的最优解就是 FastAPI。
bash# 创建虚拟环境(强烈建议)
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# 安装 FastAPI + Uvicorn(ASGI 服务器)
pip install fastapi ucorn[standard]创建 main.py:
pythonfrom fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello, FastAPI"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}启动服务:
bashuvicorn main:app --reload --host 0.0.0.0 --port 8000访问 http://127.0.0.1:8000,你会看到 JSON 响应。
访问 http://127.0.0.1:8000/docs——交互式 API 文档自动生成,可以直接在页面测试接口。
💡 这就是 FastAPI 的杀手级特性:代码即文档,文档即测试。不用写 Swagger,不用维护 Postman 集合。
FastAPI 的灵魂是 Pydantic。你定义的每一个请求体/响应体,都是一个 Pydantic 模型,类型不对直接报错,不用写一行校验代码。
pythonfrom pydantic import BaseModel, EmailStr, Field
class UserCreate(BaseModel):
username: str = Field(..., min_length=3, max_length=20)
email: EmailStr # 自动校验邮箱格式
age: int = Field(..., ge=18, le=120) # 范围校验
password: str = Field(..., min_length=8)
class UserResponse(BaseModel):
id: int
username: str
email: str
created_at: str
class Config:
from_attributes = True # 兼容 ORM 模型实战效果:
python@app.post("/users/", response_model=UserResponse)
def create_user(user: UserCreate):
# 如果请求体里 age=15,FastAPI 自动返回 422 错误
# 如果 email 不是合法格式,自动返回 422 错误
# 你不需要写任何 if 判断
return {"id": 1, "username": user.username, "email": user.email, "created_at": "2026-06-01"}参数类型 | 位置 | 用法 | 示例 |
|---|---|---|---|
路径参数 | URL 路径 | 必填,用于标识资源 | /users/{user_id} |
查询参数 | ?key=value | 选填,用于筛选/分页 | /users?skip=0&limit=10 |
请求体 | Body | 复杂数据,POST/PUT 用 | JSON 对象 |
python@app.get("/users/{user_id}/orders/{order_id}")
def get_order(
user_id: int, # 路径参数
order_id: int, # 路径参数
status: str = "pending", # 查询参数(有默认值)
q: str = None # 查询参数(可选)
):
return {"user_id": user_id, "order_id": order_id, "status": status}依赖注入(Dependency Injection) 是 FastAPI 区别于 Flask 的核心架构优势。它让你把认证、数据库连接、权限校验这些横切关注点,从业务逻辑中彻底剥离。
pythonfrom fastapi import Depends, HTTPException, status
# 模拟数据库
fake_db = {"user1": {"id": 1, "username": "alice", "role": "admin"}}
# 依赖函数:根据 token 获取当前用户
async def get_current_user(token: str = Depends(verify_token)):
user = fake_db.get(token)
if not user:
raise HTTPException(status_code=401, detail="Invalid token")
return user
def verify_token(token: str = Depends()):
if token != "secret-token":
raise HTTPException(status_code=403, detail="Invalid credentials")
return "user1" # 返回用户标识
# 使用依赖
@app.get("/users/me")
def read_users_me(current_user: dict = Depends(get_current_user)):
return current_user为什么这很重要?
read_users_me 完全不关心认证逻辑get_current_userFastAPI 天然适配异步数据库操作。以 SQLAlchemy 2.0 + asyncpg(PostgreSQL) 为例:
bashpip install sqlalchemy[asyncio] asyncpgpythonfrom sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker, declarative_base
DATABASE_URL = "postgresql+asyncpg://user:pass@localhost/mydb"
engine = create_async_engine(DATABASE_URL, echo=True)
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
Base = declarative_base()
# 定义模型
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
username = Column(String, unique=True)
email = Column(String)
# 依赖:获取数据库会话
async def get_db():
async with AsyncSessionLocal() as session:
yield session
# CRUD 接口
@app.post("/users/", response_model=UserResponse)
async def create_user(user: UserCreate, db: AsyncSession = Depends(get_db)):
db_user = User(username=user.username, email=user.email)
db.add(db_user)
await db.commit()
await db.refresh(db_user)
return db_user
@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int, db: AsyncSession = Depends(get_db)):
result = await db.get(User, user_id)
if not result:
raise HTTPException(status_code=404, detail="User not found")
return resultpythonfrom fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"], # 前端地址
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# 自定义中间件:记录请求耗时
@app.middleware("http")
async def add_process_time_header(request, call_next):
import time
start = time.time()
response = await call_next(request)
process_time = time.time() - start
response.headers["X-Process-Time"] = str(process_time)
return responsebashpip install python-jose[cryptography] passlib[bcrypt]pythonfrom jose import JWTError, jwt
from passlib.context import CryptContext
from datetime import datetime, timedelta
SECRET_KEY = "your-secret-key-change-in-production"
ALGORITHM = "HS256"
ACCESS_TOKEN_EXPIRE_MINUTES = 30
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def create_access_token(data: dict):
to_encode = data.copy()
expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
def verify_token(token: str = Depends(oauth2_scheme)):
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if not username:
raise HTTPException(status_code=401, detail="Invalid token")
return username
except JWTError:
raise HTTPException(status_code=401, detail="Invalid token")
# 登录接口
@app.post("/token")
def login(form_data: OAuth2PasswordRequestForm = Depends()):
user = fake_db.get(form_data.username)
if not user or not pwd_context.verify(form_data.password, user["password_hash"]):
raise HTTPException(status_code=401, detail="Incorrect credentials")
access_token = create_access_token(data={"sub": form_data.username})
return {"access_token": access_token, "token_type": "bearer"}myapi/
├── app/
│ ├── __init__.py
│ ├── main.py # 入口
│ ├── models.py # 数据库模型
│ ├── schemas.py # Pydantic 模型
│ ├── crud.py # 数据库操作
│ ├── dependencies.py # 依赖注入
│ └── routers/
│ ├── auth.py # 认证路由
│ └── items.py # 业务路由
├── requirements.txt
└── .envschemas.py:
pythonfrom pydantic import BaseModel
from typing import Optional
class ItemBase(BaseModel):
title: str
description: Optional = None
price: float
class ItemCreate(ItemBase):
pass
class ItemResponse(ItemBase):
id: int
owner_id: int
class Config:
from_attributes = Truerouters/items.py:
pythonfrom fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from app import crud, schemas
from app.dependencies import get_db, get_current_user
router = APIRouter(prefix="/items", tags=["items"])
@router.post("/", response_model=schemas.ItemResponse)
async def create_item(
item: schemas.ItemCreate,
db: AsyncSession = Depends(get_db),
current_user: dict = Depends(get_current_user)
):
return await crud.create_item(db=db, item=item, owner_id=current_user["id"])
@router.get("/{item_id}", response_model=schemas.ItemResponse)
async def read_item(
item_id: int,
db: AsyncSession = Depends(get_db),
current_user: dict = Depends(get_current_user)
):
item = await crud.get_item(db=db, item_id=item_id)
if item.owner_id != current_user["id"]:
raise HTTPException(status_code=403, detail="Not your item")
return itemmain.py:
pythonfrom fastapi import FastAPI
from app.routers import auth, items
app = FastAPI(title="My API", version="1.0.0")
app.include_router(auth.router)
app.include_router(items.router)
@app.get("/health")
def health_check():
return {"status": "ok"}部署方式 | 适用场景 | 命令 |
|---|---|---|
Uvicorn 直接运行 | 开发/小流量 | uvicorn app.main:app --host 0.0.0.0 --port 8000 |
Gunicorn + Uvicorn | 生产推荐 | gunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000 |
Docker 容器化 | 云部署/K8s | 见下方 Dockerfile |
云托管 | 快速上线 | 部署到 Railway / Render / AWS ECS |
Dockerfile:
dockerfileFROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:8000"]bashdocker build -t myapi .
docker run -p 8000:8000 myapi场景 | 推荐 | 理由 |
|---|---|---|
写 REST API | FastAPI ✅ | 性能 + 效率 + 自动文档,三者兼顾 |
写全栈 Web 应用(含模板渲染) | Django | 自带 ORM + Admin + 模板引擎,开箱即用 |
极简微服务/原型 | Flask | 够用就好,不需要类型注解负担 |
高并发实时通信 | FastAPI + WebSocket | 原生支持,比 Flask-SocketIO 更优雅 |
AI/ML 模型服务化 | FastAPI ✅ | 类型校验 + 异步 + 文档,完美匹配模型接口场景 |
阶段 | 时间 | 内容 |
|---|---|---|
基础语法 | 3 天 | Python 类型注解、Pydantic 基础、路径操作 |
核心特性 | 5 天 | 依赖注入、响应模型、状态码、异常处理 |
数据库实战 | 5 天 | SQLAlchemy 2.0 异步、CRUD 完整流程 |
认证授权 | 3 天 | OAuth2 + JWT、权限依赖 |
中间件与测试 | 3 天 | 自定义中间件、pytest + httpx 写测试 |
部署上线 | 2 天 | Docker、Gunicorn、Nginx 反向代理 |
实战项目 | 7 天 | 从零构建一个完整的 REST API(带用户认证 + CRUD + 文档) |
推荐资源:
fastapi-practiceFastAPI 的设计哲学很清晰:让正确的事情变得简单,让错误的事情变得困难。
类型注解让你写代码时就在写文档,Pydantic 让你不用写校验逻辑,依赖注入让你不用复制粘贴认证代码。
它不是银弹,但如果你在 2025 年用 Python 写 API,先用 FastAPI,不会错。
打开终端,pip install fastapi uvicorn,从第一个 @app.get("/") 开始。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。