FastAPI 是什么

FastAPI 是当前 Python 社区最受欢迎的 Web 框架之一,它用一个朴素的想法解决了传统框架的痛点:把 Python 的类型提示当作接口契约,让校验、序列化、文档自动生成。你写函数签名时标注参数类型,FastAPI 就自动完成请求解析、数据校验、错误返回,甚至生成一份可点击试用的 OpenAPI 文档。

它基于两个成熟组件:Starlette 提供 ASGI 异步能力与路由,Pydantic 提供数据模型与校验。因此它天生支持异步并发,性能接近 Node.js 与 Go 的同类方案,同时保持了「纯 Python、可读性好」的开发体验。

选框架看三件事:开发效率、运行性能、生态成熟度。FastAPI 在这三件事上都很能打——类型提示即文档,异步开箱即用,社区插件覆盖了认证、ORM、任务队列等常见需求。
本文核心知识点
  • 类型提示函数签名里的类型标注就是请求/响应契约,自动完成校验与序列化。
  • Pydantic声明式数据模型,复杂嵌套校验只需一个类。
  • 依赖注入用 Depends 组织数据库连接、鉴权、会话等横切逻辑。
  • 自动文档/docs 提供可交互的 Swagger UI,接口调试零成本。
FastAPI 示意:API 接口节点、闪电符号与数据管道组成的蓝色扁平插画
类型即契约:一份类型标注同时驱动校验、序列化、文档与客户端代码生成。

第一个接口:Hello World

先建好虚拟环境(方法见同频道的《Python 开发环境搭建与虚拟环境管理实战》),安装 FastAPI 与 Uvicorn,然后写一个最小应用:

pip install "fastapi" "uvicorn[standard]"

# main.py
from fastapi import FastAPI

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

@app.get("/")
def read_root():
    return {"message": "Hello, JijiyunCode"}

@app.get("/ping")
def ping():
    return {"status": "ok"}

启动并访问:

uvicorn main:app --reload --port 8000
# 浏览器打开 http://127.0.0.1:8000/docs 查看自动生成的交互文档
# 打开 http://127.0.0.1:8000/openapi.json 查看 OpenAPI 规范

值得注意的细节:--reload 让代码改动即时生效,只用于开发;路由函数返回普通字典,FastAPI 自动序列化为 JSON——你不需要手动 json.dumps,也不用声明响应模型,类型标注已经替你说清楚了。

路径、查询参数与请求体

真实接口需要从三个位置拿数据:URL 路径、查询字符串、请求体。FastAPI 用类型标注区分它们——函数签名即参数来源:

from fastapi import FastAPI, Query, Path

app = FastAPI()

@app.get("/users/{user_id}")
def get_user(
    user_id: int = Path(..., description="用户 ID"),
    verbose: bool = Query(False, description="是否返回详情"),
):
    return {"id": user_id, "verbose": verbose}

@app.post("/users")
def create_user(payload: dict):
    # 请求体为 JSON,直接可用
    return {"received": payload}
参数来源写法典型场景
路径参数user_id: int资源标识,如 /users/42
查询参数q: str | None = None过滤、分页、搜索
请求体payload: Item创建/更新资源
请求头x_token: str = Header(...)认证信息、自定义头

注意路径参数要声明在路径里({user_id}),查询参数直接写进签名——FastAPI 会按名字自动匹配。给参数加默认值表示可选,用 ... 表示必填,语义一目了然。

Pydantic 数据校验

把 payload: dict 换成 Pydantic 模型后,校验能力立刻升级:字段缺失、类型错误、非法枚举都会自动返回带详细信息的 422 错误,无需手写任何校验代码。

from pydantic import BaseModel, Field

class Item(BaseModel):
    name: str = Field(..., min_length=1, max_length=50)
    price: float = Field(..., gt=0)
    tags: list[str] = Field(default_factory=list)

@app.post("/items")
def create_item(item: Item):
    # item 已通过校验,字段类型确定,IDE 有完整提示
    return {"id": 1, **item.model_dump()}

常用技巧:

  • 嵌套模型:模型字段可以是另一个模型,级联校验自动完成。
  • 响应模型:@app.post(..., response_model=ItemOut) 控制返回字段与过滤敏感信息。
  • 字段约束:gt/ge/lt/le、min_length/max_length、pattern 覆盖常见规则。
  • 可选与默认:field: int | None = None 声明可空字段。

校验失败时的响应结构也固定(422 + errors 数组),前端与网关可以统一处理,这是把校验交给框架的最大红利。

依赖注入与数据库

依赖注入(Depends)解决「每个接口都要拿同一个东西」的重复问题——数据库会话、当前用户、配置对象,声明一次,处处复用,还支持嵌套与缓存。

from fastapi import Depends, FastAPI

app = FastAPI()

def get_db():
    db = create_connection()   # 伪代码:建立连接
    try:
        yield db               # yield 写法支持用完自动释放
    finally:
        db.close()

@app.get("/items")
def list_items(db=Depends(get_db)):
    return db.query_all("SELECT * FROM items")

# 依赖里再依赖:鉴权 → 用户 → 数据,按需组合
def get_current_user(token: str = Depends(oauth_scheme)):
    return decode_token(token)

@app.get("/me")
def me(user=Depends(get_current_user)):
    return {"user": user.username}

与 SQLAlchemy 搭配是社区标准组合:用 sessionmaker 创建会话工厂,在依赖里 yield 会话并负责提交/回滚,业务代码完全不用关心连接生命周期。测试时把 get_db 覆盖成测试库,一行代码切换环境。

中间件与鉴权

中间件在请求进入路由之前、响应离开之前执行,适合日志、CORS、限流、统一异常处理。CORS 是前后端分离最常见的配置:

from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["https://your-site.example"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

鉴权的主流做法是 OAuth2 密码流 + JWT:FastAPI 官方文档提供了完整示例,核心流程是——

  • 登录接口校验用户名密码,签发 JWT(含过期时间与用户标识);
  • 受保护接口从 Authorization 头取 token,验签后解析出用户;
  • 把「解析当前用户」封装成依赖,接口里声明 user=Depends(get_current_user) 即自动拦截。

生产级补充:密码用 bcrypt/argon2 哈希、token 设置合理过期与刷新机制、敏感操作加二次校验。鉴权逻辑集中在依赖里,路由代码保持干净。