> ## Documentation Index
> Fetch the complete documentation index at: https://docs.akria.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Day 15 | FastAPI 快速入门

> 从 0 到 1 构建第一个高性能 API，理解 RESTful 与自动化文档

<Info>
  **今日目标**：FastAPI 是当下最火的 Python Web 框架。今天我们不只是写个 "Hello World"，而是要彻底搞懂 **"什么是 RESTful API"**、**"URL 如何传参"**、**"如何启动服务器"** 以及 **"Swagger 文档如何自动生成"** 这四个核心问题。今天不只是写代码，而是要彻底理解 **"FastAPI 为什么比 Flask 快"**、**"路径参数和查询参数的区别"** 以及 **"为什么需要 ASGI 服务器"**。
</Info>

## <span style={{ display: 'inline-flex', alignItems: 'center', gap: '8px' }}><Icon icon="book" size={26} color="#059669" /> 学习内容 (30 mins)</span>

在开始写代码前，先搞懂这些核心概念，否则后面的代码你会看得云里雾里。

<AccordionGroup>
  <Accordion title="什么是 FastAPI？(10 mins)" icon="code">
    **FastAPI 是什么？**

    FastAPI 是一个现代、快速的 Python Web 框架，用于构建 API。它基于 Python 3.6+ 的类型提示（Type Hints）和异步编程（Async/Await）。

    **为什么选择 FastAPI？**

    * **性能极快**：基于 Starlette 和 Pydantic，性能接近 Node.js 和 Go
    * **自动文档**：自动生成 Swagger UI 和 ReDoc 文档
    * **类型安全**：基于 Python 类型提示，IDE 支持好
    * **异步支持**：原生支持异步编程，适合高并发场景
    * **数据验证**：基于 Pydantic，自动验证请求数据

    **FastAPI vs Flask vs Django**：

    * **Flask**：轻量级，但需要手动写很多代码（路由、验证、文档）
    * **Django**：功能全面，但重量级，学习曲线陡
    * **FastAPI**：现代化，自动生成文档，性能好，适合 API 开发

    **FastAPI 的核心特性**：

    * **自动类型转换**：URL 参数自动转换为指定类型
    * **自动数据验证**：基于 Pydantic 自动验证请求数据
    * **自动文档生成**：访问 `/docs` 即可查看交互式 API 文档
    * **异步支持**：原生支持 `async/await`，适合高并发
  </Accordion>

  <Accordion title="RESTful API 基础 (10 mins)" icon="server">
    **什么是 RESTful API？**

    REST（Representational State Transfer）是一种 API 设计风格，通过 HTTP 方法（GET、POST、PUT、DELETE）操作资源。

    **RESTful 设计原则**：

    * **资源导向**：URL 表示资源，如 `/users`、`/servers`
    * **HTTP 方法**：GET（查询）、POST（创建）、PUT（更新）、DELETE（删除）
    * **状态码**：200（成功）、201（创建）、400（错误）、404（未找到）
    * **无状态**：每个请求都是独立的，不依赖之前的请求

    **路径参数 vs 查询参数**：

    * **路径参数 (Path Parameters)**：
      * 位置：URL 路径的一部分，如 `/users/5` 中的 `5`
      * 用途：定位特定资源（获取 ID 为 5 的用户）
      * 语法：在路径中写 `{user_id}`，如 `/users/{user_id}`
      * 示例：`GET /users/5` - 获取 ID 为 5 的用户
    * **查询参数 (Query Parameters)**：
      * 位置：URL 问号 `?` 后面的键值对
      * 用途：过滤、排序、分页
      * 语法：函数参数，但不在路径中写 `{xx}`
      * 示例：`GET /users?limit=10&sort=age` - 获取前 10 个用户，按年龄排序

    **实际应用场景**：

    * 路径参数：获取详情、删除资源
    * 查询参数：列表查询、搜索、分页、筛选
  </Accordion>

  <Accordion title="ASGI 服务器 (10 mins)" icon="terminal">
    **什么是 ASGI？**

    ASGI（Asynchronous Server Gateway Interface）是 Python 异步 Web 服务器和框架之间的标准接口。

    **为什么需要 ASGI 服务器？**

    * **FastAPI 只是框架**：它定义了路由、处理逻辑，但不负责监听端口
    * **Uvicorn 是服务器**：负责监听 HTTP 请求，将请求转交给 FastAPI 处理
    * **类比**：FastAPI 是"厨师"（处理业务逻辑），Uvicorn 是"服务员"（接收订单并传递给厨师）

    **Uvicorn 的作用**：

    * 监听端口（默认 8000）
    * 接收 HTTP 请求
    * 将请求转交给 FastAPI 处理
    * 将 FastAPI 的响应返回给客户端

    **启动命令解析**：

    ```bash theme={null}
    uvicorn 15_main:app --reload
    ```

    * `15_main`：Python 文件名（不含 .py）
    * `app`：FastAPI 实例的变量名
    * `--reload`：开发模式，代码修改后自动重启（生产环境不要用）

    **生产环境部署**：

    * 开发环境：直接使用 `uvicorn`（简单快速）
    * 生产环境：使用 `gunicorn + uvicorn`（多进程，更稳定）
  </Accordion>
</AccordionGroup>

***

## <span style={{ display: 'inline-flex', alignItems: 'center', gap: '8px' }}><Icon icon="code" size={26} color="#059669" /> 代码任务 (90 mins)</span>

<Steps>
  <Step title="环境准备">
    在开始之前，确保你的环境已准备好：

    * **Python 环境**：需要 Python 3.7+（推荐 3.9+）
    * **虚拟环境**：确保虚拟环境已激活（参考 Day 08）
    * **文本编辑器**：继续使用 nano 或 vi/vim（参考 Day 01）

    <CodeGroup>
      ```bash 检查 Python 版本 theme={null}
      # 检查 Python 版本
      python3 --version
      # 应该输出: Python 3.9.x 或更高版本

      # 确保虚拟环境已激活（提示符前有 (.venv)）
      source .venv/bin/activate
      ```

      ```bash 安装 FastAPI 和 Uvicorn theme={null}
      # 安装 FastAPI 框架
      pip install fastapi

      # 安装 ASGI 服务器
      pip install uvicorn[standard]
      # [standard] 包含额外的性能优化依赖

      # 验证安装
      python -c "import fastapi; print('FastAPI installed successfully')"
      python -c "import uvicorn; print('Uvicorn installed successfully')"
      ```
    </CodeGroup>

    **为什么需要两个包？**

    * **fastapi**：Web 框架，定义路由和处理逻辑
    * **uvicorn**：ASGI 服务器，负责监听端口和处理 HTTP 请求

    **验证步骤**：

    1. 检查 Python 版本是否符合要求
    2. 确认虚拟环境已激活
    3. 验证 fastapi 和 uvicorn 安装成功
  </Step>

  <Step title="任务 A：编写第一个 API">
    新建文件 `15_main.py`，实现第一个 FastAPI 应用。

    **任务分解**：

    1. 创建 FastAPI 应用实例
    2. 定义根路由（GET /）
    3. 定义带路径参数的路由（GET /items/{item_id}）

    <CodeGroup>
      ```python 15_main.py theme={null}
      #!/usr/bin/env python3
      """
      Day 15 - FastAPI 快速入门
      演示基础路由、路径参数和查询参数
      """

      from fastapi import FastAPI

      # ========== 1. 初始化 FastAPI 应用 ==========
      # FastAPI 是一个类，需要实例化
      # 参数说明：
      # - title: API 的标题（会显示在 Swagger 文档中）
      # - description: API 的描述（会显示在 Swagger 文档中）
      # - version: API 的版本号
      app = FastAPI(
          title="My First Ops API",
          description="这是一个用于演示 FastAPI 基础功能的文档",
          version="1.0.0"
      )

      # ========== 2. 定义根路由 (GET 请求) ==========
      # @app.get("/") 是装饰器，表示这是一个 GET 请求的路由
      # "/" 是路径，表示根路径
      # 访问 http://localhost:8000/ 时触发这个函数
      @app.get("/")
      def read_root():
          """
          根路由：返回 API 状态信息
          
          返回:
              包含消息和状态的字典
          """
          return {
              "message": "Hello, FastAPI!",
              "status": "running"
          }

      # ========== 3. 路径参数示例 ==========
      # {item_id} 是路径参数，用花括号包裹
      # item_id: int 是类型注解，FastAPI 会自动将 URL 中的字符串转换为整数
      # 访问 http://localhost:8000/items/5 时，item_id 的值是 5
      @app.get("/items/{item_id}")
      def read_item(item_id: int):
          """
          获取单个项目信息
          
          参数:
              item_id: 项目 ID（路径参数）
          
          返回:
              包含项目 ID 和是否为偶数的字典
          """
          return {
              "item_id": item_id,
              "is_even": item_id % 2 == 0  # 判断是否为偶数
          }

      # ========== 4. 查询参数示例 ==========
      # skip 和 limit 没有在路径中，所以 FastAPI 自动识别为查询参数
      # = 0 和 = 2 是默认值，如果请求中没有提供这些参数，使用默认值
      # 访问 http://localhost:8000/servers?skip=1&limit=2 时：
      #   - skip = 1
      #   - limit = 2
      # 访问 http://localhost:8000/servers 时：
      #   - skip = 0（默认值）
      #   - limit = 2（默认值）

      # 模拟数据库数据
      fake_db = [
          {"name": "Server A", "status": "running"},
          {"name": "Server B", "status": "stopped"},
          {"name": "Server C", "status": "running"},
          {"name": "Server D", "status": "running"},
      ]

      @app.get("/servers")
      def list_servers(skip: int = 0, limit: int = 2):
          """
          分页获取服务器列表
          
          参数:
              skip: 跳过多少条记录（默认 0）
              limit: 返回多少条记录（默认 2）
          
          返回:
              服务器列表（字典列表）
          """
          # 使用 Python 切片实现分页
          # fake_db[skip:skip+limit] 表示从 skip 开始，取 limit 条
          return fake_db[skip : skip + limit]
      ```
    </CodeGroup>

    **代码解释**：

    * **FastAPI 实例**：`app = FastAPI(...)` 创建应用实例
    * **路由装饰器**：`@app.get("/")` 定义 GET 路由
    * **路径参数**：`{item_id}` 在路径中，`item_id: int` 自动类型转换
    * **查询参数**：函数参数不在路径中，自动识别为查询参数
    * **默认值**：`skip: int = 0` 设置默认值，参数可选

    **运行脚本**：

    ```bash theme={null}
    # 启动服务器
    uvicorn 15_main:app --reload

    # 看到以下输出表示成功：
    # INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
    # INFO:     Started reloader process [xxxxx] using WatchFiles
    # INFO:     Started server process [xxxxx]
    # INFO:     Waiting for application startup.
    # INFO:     Application startup complete.
    ```

    **验证步骤**：

    1. 启动服务器后，访问 `http://localhost:8000/`
       * 应该看到：`{"message":"Hello, FastAPI!","status":"running"}`
    2. 访问 `http://localhost:8000/items/5`
       * 应该看到：`{"item_id":5,"is_even":false}`
    3. 访问 `http://localhost:8000/items/abc`
       * 应该看到错误：`{"detail":[{"loc":["path","item_id"],"msg":"value is not a valid integer"...}]}`
       * 这说明 FastAPI 自动验证了类型
    4. 访问 `http://localhost:8000/servers`
       * 应该看到前 2 条记录（默认 limit=2）
    5. 访问 `http://localhost:8000/servers?skip=1&limit=2`
       * 应该看到从第 2 条开始的 2 条记录

    **常见错误**：

    <Warning>
      * ❌ `ModuleNotFoundError: No module named 'fastapi'` - FastAPI 未安装，执行 `pip install fastapi`
      * ❌ `ModuleNotFoundError: No module named 'uvicorn'` - Uvicorn 未安装，执行 `pip install uvicorn`
      * ❌ `Address already in use` - 端口 8000 被占用，使用 `--port 8001` 指定其他端口
      * ❌ `ValueError: invalid literal for int()` - 路径参数类型转换失败，检查 URL 中的参数类型
    </Warning>
  </Step>

  <Step title="任务 B：体验 Swagger UI 自动文档">
    FastAPI 的亮点：自动生成交互式 API 文档。

    **访问 Swagger UI**：

    1. 确保服务器正在运行（`uvicorn 15_main:app --reload`）
    2. 打开浏览器，访问：`http://localhost:8000/docs`
    3. 你会看到一个蓝色的界面，显示所有 API 端点

    **使用 Swagger UI 测试 API**：

    1. 点击 `/servers` 旁边的绿色 **GET** 按钮
    2. 点击右侧的 **Try it out** 按钮
    3. 在参数输入框中：
       * `skip` 输入 `1`
       * `limit` 输入 `2`
    4. 点击蓝色大按钮 **Execute**
    5. 查看 **Response Body**，应该能看到 `Server B` 和 `Server C`

    **Swagger UI 的功能**：

    * **查看所有 API**：自动列出所有定义的路由
    * **查看参数说明**：显示每个参数的类型、是否必需、默认值
    * **在线测试**：可以直接在浏览器中测试 API，无需 Postman
    * **查看响应格式**：显示 API 返回的数据结构

    **其他文档界面**：

    * **Swagger UI**：`http://localhost:8000/docs`（交互式，推荐）
    * **ReDoc**：`http://localhost:8000/redoc`（更美观的文档样式）
    * **OpenAPI JSON**：`http://localhost:8000/openapi.json`（机器可读的 API 规范）

    **为什么 Swagger UI 很重要？**

    * **自动生成**：不需要手写 API 文档，减少维护成本
    * **实时同步**：代码修改后，文档自动更新
    * **交互测试**：前端开发者可以直接在文档中测试 API
    * **类型准确**：基于代码生成，不会出现文档和代码不一致的问题
  </Step>
</Steps>

***

## <span style={{ display: 'inline-flex', alignItems: 'center', gap: '8px' }}><Icon icon="lightbulb" size={26} color="#059669" /> 拓展任务 (30 mins)</span>

<CardGroup cols={2}>
  <Card title="挑战 1：添加更多路由" icon="code">
    **任务**：添加以下路由：

    * `GET /health` - 返回健康检查信息
    * `GET /users/{user_id}/posts/{post_id}` - 嵌套路径参数
    * `GET /search?q=keyword&page=1` - 搜索接口（多个查询参数）

    **提示**：

    * 路径参数用 `{变量名}` 定义
    * 查询参数直接在函数参数中定义
    * 可以组合使用路径参数和查询参数
  </Card>

  <Card title="挑战 2：理解类型转换" icon="check">
    **任务**：尝试以下 URL，观察 FastAPI 如何处理类型转换：

    * `GET /items/123` - 整数
    * `GET /items/abc` - 非整数（应该报错）
    * `GET /items/3.14` - 浮点数（应该报错，因为类型是 int）

    **思考**：FastAPI 如何自动验证和转换类型？
  </Card>
</CardGroup>

***

## <span style={{ display: 'inline-flex', alignItems: 'center', gap: '8px' }}><Icon icon="file" size={26} color="#059669" /> 今日产出物</span>

* `15_main.py` - FastAPI 应用主文件
* 运行中的 API 服务（可通过浏览器访问）

***

## <span style={{ display: 'inline-flex', alignItems: 'center', gap: '8px' }}><Icon icon="github" size={26} color="#059669" /> 参考代码</span>

<CardGroup cols={2}>
  <Card title="查看参考代码" icon="code" href="https://github.com/akriamail/insightful-ops/tree/main/docs/mintlify/scripts/training/30daystudy/week-3/day-15">
    在 GitHub 查看完整的 FastAPI 示例代码

    <br />

    <small>包含 15\_main.py 和完整项目结构</small>
  </Card>

  <Card title="在线运行" icon="play" href="https://replit.com">
    使用在线编辑器测试 FastAPI

    <br />

    <small>快速体验 API 开发</small>
  </Card>
</CardGroup>

***

## 实际应用场景

<CardGroup cols={2}>
  <Card title="FastAPI 在运维中的应用" icon="server">
    * **监控 API**：提供服务器监控数据的查询接口
    * **配置管理**：通过 API 管理服务器配置
    * **日志查询**：提供日志搜索和查询接口
    * **自动化工具**：为自动化脚本提供 RESTful API
    * **微服务架构**：构建轻量级微服务
  </Card>

  <Card title="RESTful API 设计最佳实践" icon="check">
    * **资源命名**：使用名词，如 `/users`、`/servers`，不要用动词
    * **HTTP 方法**：GET（查询）、POST（创建）、PUT（更新）、DELETE（删除）
    * **状态码**：正确使用 HTTP 状态码（200、201、400、404、500）
    * **版本控制**：大型 API 应该使用版本号，如 `/v1/users`
    * **文档完善**：利用 FastAPI 自动生成文档，保持文档和代码同步
  </Card>
</CardGroup>

<Tip>
  **与 Day 16 的关联**：今天学习的 FastAPI 基础路由，明天会学习如何使用 Pydantic 进行数据验证，让 API 能够自动验证和转换请求数据。
</Tip>

***

<CardGroup cols={2}>
  <Card title="上一周: Python 实战" href="/training/30daystudy/day-14">
    Day 14 | 第二阶段复盘
  </Card>

  <Card title="下一天: 数据验证" href="/training/30daystudy/day-16">
    Day 16 | Pydantic 数据验证
  </Card>
</CardGroup>
