FastAPI 快速上手:30 分钟写一个可部署的 REST API

站长 2026-09-29 0 约 2 分钟 533 字
#Python#FastAPI#Web开发#REST API#后端

为什么选 FastAPI

Python Web 框架里,Flask 简单但太原始,Django 功能全但太重。FastAPI 是新一代的选择:

  • 快:性能接近 Node.js 和 Go(基于 Starlette + Pydantic)
  • 自动文档:写完代码自动生成交互式 API 文档,前端看了直呼内行
  • 类型安全:用 Python 类型注解做参数校验,类型错了直接返回 422
  • 异步原生:天生支持 async/await,IO 密集场景性能碾压
pip install fastapi uvicorn

第一个接口:5 行代码

# main.py
from fastapi import FastAPI

app = FastAPI(title="我的第一个API")

@app.get("/")
def hello():
    return {"message": "Hello FastAPI"}

@app.get("/items/{item_id}")
def get_item(item_id: int):   # 声明 int 类型,自动转换和校验
    return {"item_id": item_id, "name": f"商品{item_id}"}

启动:

uvicorn main:app --reload --port 8000
  • --reload:改代码自动重启,开发必备
  • main:app:指 main.py 文件里的 app 对象

现在访问:

  • http://127.0.0.1:8000/items/42 → 返回 JSON
  • http://127.0.0.1:8000/items/abc → 自动返回 422 错误(因为 abc 不是 int)
  • http://127.0.0.1:8000/docs → 自动生成的 Swagger 文档页面,可以直接在页面上测试接口

参数校验:Pydantic 的威力

POST 请求的数据校验,用 Pydantic 模型声明:

from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI()

class ItemCreate(BaseModel):
    name: str = Field(min_length=1, max_length=50, description="商品名")
    price: float = Field(gt=0, description="价格必须大于0")
    stock: int = Field(default=0, ge=0)
    tags: list[str] = []

@app.post("/items")
def create_item(item: ItemCreate):
    return {"message": "创建成功", "data": item}

发请求时:

  • 字段缺失/类型错误/不满足约束 → 自动返回详细的 422 错误信息
  • 一切正常 → item 是一个类型安全的对象,IDE 有完整提示

再也不用手写 if not name: return error 这类校验代码。

查询参数与路径参数

from typing import Optional

@app.get("/items")
def list_items(
    keyword: Optional[str] = None,   # 可选查询参数 ?keyword=xxx
    page: int = 1,                    # 带默认值
    size: int = Field(default=20, le=100),  # 限制最大100
):
    return {"keyword": keyword, "page": page, "size": size}

一个完整的小项目:待办事项 API

把前面的知识串起来,写一个带增删改查的完整 API:

# todo.py
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field

app = FastAPI(title="待办事项API")

# 用列表模拟数据库(下节换成真实数据库)
todos = []
next_id = 1

class TodoCreate(BaseModel):
    title: str = Field(min_length=1, max_length=100)
    done: bool = False

class Todo(TodoCreate):
    id: int

@app.get("/todos", response_model=list[Todo])
def list_todos():
    """获取所有待办"""
    return todos

@app.post("/todos", response_model=Todo, status_code=201)
def create_todo(item: TodoCreate):
    """创建待办"""
    global next_id
    todo = Todo(id=next_id, **item.model_dump())
    next_id += 1
    todos.append(todo)
    return todo

@app.get("/todos/{todo_id}", response_model=Todo)
def get_todo(todo_id: int):
    """获取单个待办"""
    for t in todos:
        if t.id == todo_id:
            return t
    raise HTTPException(status_code=404, detail="待办不存在")

@app.put("/todos/{todo_id}", response_model=Todo)
def update_todo(todo_id: int, item: TodoCreate):
    """更新待办"""
    for i, t in enumerate(todos):
        if t.id == todo_id:
            todos[i] = Todo(id=todo_id, **item.model_dump())
            return todos[i]
    raise HTTPException(status_code=404, detail="待办不存在")

@app.delete("/todos/{todo_id}", status_code=204)
def delete_todo(todo_id: int):
    """删除待办"""
    for i, t in enumerate(todos):
        if t.id == todo_id:
            todos.pop(i)
            return
    raise HTTPException(status_code=404, detail="待办不存在")

response_model 的好处:自动过滤返回值(比如不暴露内部字段)、生成准确的文档、做响应校验。

连接真实数据库(以 SQLite + SQLAlchemy 为例)

pip install sqlalchemy
# database.py
from sqlalchemy import Column, Integer, String, Boolean, create_engine
from sqlalchemy.orm import declarative_base, sessionmaker

engine = create_engine("sqlite:///./todos.db", connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(bind=engine)
Base = declarative_base()

class TodoModel(Base):
    __tablename__ = "todos"
    id = Column(Integer, primary_key=True, index=True)
    title = Column(String(100), nullable=False)
    done = Column(Boolean, default=False)

Base.metadata.create_all(engine)  # 自动建表

在 FastAPI 中用依赖注入管理数据库会话:

from fastapi import Depends
from sqlalchemy.orm import Session

def get_db():
    """每个请求一个会话,结束自动关闭"""
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()

@app.get("/todos")
def list_todos(db: Session = Depends(get_db)):
    return db.query(TodoModel).all()

@app.post("/todos", status_code=201)
def create_todo(item: TodoCreate, db: Session = Depends(get_db)):
    todo = TodoModel(**item.model_dump())
    db.add(todo)
    db.commit()
    db.refresh(todo)
    return todo

生产部署

开发用 --reload,生产环境这样跑:

# 4 个 worker 进程,绑定所有网卡
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4

更稳的方案是 gunicorn 管理 uvicorn worker(Linux):

pip install gunicorn
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000

前面再挂 Nginx 反向代理,搞定域名和 HTTPS,就是标准的生产架构。

进阶方向

到这里你已经能写可用的 API 了。下一步按需学习:

  • 用户认证:fastapi-users 或手写 JWT(python-jose)
  • 跨域 CORS:前端联调必配 CORSMiddleware
  • 后台任务:BackgroundTasks 处理发邮件这类慢操作
  • 限流:slowapi 防止接口被刷
  • 测试:fastapi.testclient 基于 httpx,写接口测试很顺手

写在最后

FastAPI 的设计哲学是「别让我重复写样板代码」。类型注解即校验、代码即文档——把这两个特性用足,你的接口开发效率会提升一个量级。建议把待办事项的例子亲手跑通,再把它改造成一个你自己真正需要的小工具。

评论 (0)

我的头像

还没有评论,快来抢沙发吧~