P07第 1 / 1 课时未开始内容版本 1.0.0 · 核验于 2026-10-26

FastAPI 基础接口

FastAPI 基础接口 · 阅读后完成下方实验与检查题,再用「标记完成」记录进度。

学习目标

前端课程写多了,接口对你来说是个黑盒:发请求、收 JSON。本课你自己把这个黑盒造出来——用 FastAPI 写一个课程查询接口,亲手决定它对错误输入怎么反应。

问题场景

假设 ReactLab 的课程数据要给另一个小工具用,它需要一个接口:

  • GET /courses 列出全部课程(支持 ?track=react 过滤)
  • GET /courses/{code} 返回单门课,不存在时明确说 404

用 Python 最快的路径就是 FastAPI:类型标注直接变成参数校验和文档,几行代码得到一个行为规矩的 API。

核心解释

先跑起来再说原理:

# main.py
from fastapi import FastAPI, HTTPException, Query

app = FastAPI(title="ReactLab 学习记录 API")

FAKE_COURSES = [
    {"code": "R08", "title": "useState 与状态快照", "track": "react"},
    {"code": "N07", "title": "服务端数据访问", "track": "nextjs"},
    {"code": "P07", "title": "FastAPI 基础接口", "track": "python"},
]

@app.get("/courses")
def list_courses(
    track: str | None = Query(default=None, max_length=20),
):
    """课程列表,可按方向过滤。"""
    rows = FAKE_COURSES
    if track:
        rows = [c for c in rows if c["track"] == track]
    return {"total": len(rows), "items": rows}

@app.get("/courses/{code}")
def get_course(code: str):
    for c in FAKE_COURSES:
        if c["code"] == code.upper():
            return c
    raise HTTPException(status_code=404, detail=f"课程 {code} 不存在")

启动并验证:

pip install fastapi uvicorn
uvicorn main:app --reload --port 8100
# 浏览器打开 http://127.0.0.1:8100/docs 看自动生成的交互文档

四件 FastAPI 替你做的事,值得逐个看清:

  1. 函数签名即接口契约。track: str | None = Query(...) 这一行同时完成三件事:声明可选查询参数、限制长度、生成文档。客户端传了超长字符串会得到 422,根本到不了你的函数体。
  2. 路径参数自动解析。{code} 里的值以字符串进入函数,需要时标注类型(如 code: int),类型不符 FastAPI 自动返回 422。
  3. 错误要显式抛。课程不存在时 raise HTTPException(404, ...),返回体是 {"detail": "..."}——不要返回 200 加一个 {"error": ...},那会让调用方必须解析 body 才知道出错了。
  4. 自动文档。/docs 页面由代码生成,接口怎么调一目了然;它不是装饰,是验证工具。

示例拆解

用 curl(或浏览器)验证上面接口的行为:

curl "http://127.0.0.1:8100/courses"
# {"total":3,"items":[...]}

curl "http://127.0.0.1:8100/courses?track=react"
# {"total":1,"items":[{"code":"R08",...}]}

curl -i "http://127.0.0.1:8100/courses/X99"
# HTTP/1.1 404 Not Found
# {"detail":"课程 X99 不存在"}

注意响应结构的决定权在你:total + items 这个外壳让前端分页组件有稳定预期,是值得保持的惯例。每个接口都返回同样形状的成功/错误结构,前端处理逻辑就能统一。

动手任务

本课实验区提供了上面 main.py 的可运行版本(本机直接运行验证输出):

  1. 给 list_courses 加一个 keyword 查询参数,按标题模糊匹配(in 判断即可)。
  2. 新增 GET /courses/{code}/exists,存在返回 {"exists": true},不存在返回 404。
  3. 用 /docs 页面验证三种情况:正常、有过滤、不存在的 code。

常见错误

  • 在函数里 print 调试却看不到输出:uvicorn 的日志和 print 都在启动终端里,不在浏览器。
  • 用可变默认值:def f(items=[]) 是 Python 经典坑,FastAPI 参数同样适用,默认值用 Query(default=None) 或 = [] 之外的安全写法。
  • 端口被占用还反复启动:Windows 下 netstat -ano | findstr 8100 找到进程再决定是否结束,别盲目换端口掩盖问题。
  • 把业务异常直接 500 给用户:可预期的失败(找不到、参数错)用 4xx 明说,500 留给真正的程序故障。

检查与复盘

完成下方检查题。自查清单:

  • 能不查文档写出带路径参数和查询参数的 GET 接口
  • 知道 404/422/500 分别该用在哪
  • 习惯先看 /docs 再手写 curl

参考资料

  • FastAPI 官方教程 —— 本课覆盖 First Steps 与 Query Parameters 两节
  • P08 课在此基础上引入 Pydantic 模型做请求体校验。
动手实验
动手实验
预览
点击「运行」在隔离沙箱中预览
检查题共 3 题,提交后立即显示解析
答案由服务端判定;答错的题会自动进入复习计划。
Q1单选简单

FastAPI 应用定义了 @app.get('/courses/{course_id}'),函数签名是 def detail(course_id: int)。访问 /courses/abc 会发生什么?(FastAPI + Pydantic v2)

Q2单选简单

FastAPI 接口查询的课程不存在时,正确的做法是?

Q3读代码中等

请求 GET /courses?track=react&page=0&limit=5 时,下面函数的 page 和 limit 分别是什么? @app.get("/courses") def list_courses( track: str | None = Query(default=None), page: int = Query(default=1, ge=1), limit: int = Query(default=20, le=100), ): ...

@app.get("/courses")
def list_courses(
    track: str | None = Query(default=None),
    page: int = Query(default=1, ge=1),
    limit: int = Query(default=20, le=100),
): ...

读完这一课了?

标记完成后,工作台会安排接下来的学习。

Command Palette

Search for a command to run...