FastAPI 基础教程:从零开始构建 API – wiki基地


FastAPI 基础教程:从零开始构建你的第一个现代 Web API

在现代 Web 开发中,API(应用程序编程接口)扮演着至关重要的角色。它们是不同软件系统之间通信的桥梁,使得前端应用、移动应用、微服务乃至第三方服务能够高效地交换数据和功能。选择一个合适的框架来构建 API,对于开发效率、性能和可维护性都至关重要。近年来,FastAPI 作为一个高性能、易于学习、易于编码且功能强大的 Python Web 框架,迅速获得了开发者的青睐。

本教程旨在为你提供一个全面的 FastAPI 入门指南。我们将从最基础的概念讲起,一步步带你了解 FastAPI 的核心特性,并最终构建一个简单的、功能性的 API。无论你是有一些 Python 基础但对 Web 框架感到陌生,还是希望寻找一个现代、高效的 API 开发工具,本教程都将为你打下坚实的基础。

阅读本文,你将学习到:

  • 什么是 FastAPI 及其核心优势?
  • 如何设置开发环境并安装 FastAPI?
  • 如何创建你的第一个 FastAPI 应用?
  • 理解路径操作(路由)和 HTTP 方法。
  • 如何处理路径参数和查询参数?
  • 如何使用 Pydantic 模型处理请求体和数据验证?
  • FastAPI 的自动交互式文档(Swagger UI & ReDoc)如何加速开发和测试?
  • 基本的错误处理和数据验证机制。

先决条件:

  • 熟悉 Python 基础语法。
  • 安装了 Python 3.7 或更高版本。
  • 了解基本的命令行操作。

预期篇幅: 约 3000 字


第一章:初识 FastAPI —— 现代 API 的新选择

1.1 什么是 FastAPI?

FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Python Web 框架。它基于标准的 Python 类型提示(Type Hints)构建,并充分利用了 ASGI(异步服务器网关接口)标准,使其天然支持异步操作,从而获得极高的性能。

1.2 为什么选择 FastAPI?

FastAPI 的流行并非偶然,它提供了一系列吸引人的特性:

  1. 高性能: FastAPI 的性能可与 NodeJS 和 Go 相媲美,是现有 Python 框架中性能最高的之一。这得益于其底层的 Starlette(轻量级 ASGI 框架)和 Pydantic(数据验证库)。
  2. 快速开发: 简洁的语法和对类型提示的强制使用,使得代码更易读、更易维护,并能显著减少由类型错误引起的 Bug。FastAPI 的设计哲学使得开发者可以用更少的代码完成更多的功能,据官方称,开发速度可提高 200% 至 300%。
  3. 减少 Bug: 基于 Pydantic 的强大数据验证功能,能在运行时自动校验请求和响应数据的类型与格式,大大减少了数据相关的错误。编辑器/IDE 对类型提示的良好支持(如自动补全、类型检查)也进一步降低了出错概率。
  4. 易于学习,易于使用: FastAPI 的学习曲线相对平缓,文档清晰详尽。其设计直观,符合 Python 开发者习惯。
  5. 自动交互式文档: 这是 FastAPI 的一大亮点。它能根据你的代码(特别是类型提示和 Pydantic 模型)自动生成符合 OpenAPI(以前称为 Swagger)和 JSON Schema 标准的 API 文档。并提供两个开箱即用的交互式文档界面:Swagger UI 和 ReDoc。开发者和前端团队可以直接在浏览器中浏览、测试 API,极大提高了协作效率。
  6. 基于标准: 完全兼容 OpenAPI 和 JSON Schema 标准,便于与其他工具和系统集成。同时基于 ASGI 标准,可以利用 Python 的 async/await 语法编写并发代码。
  7. 强大的编辑器支持: 类型提示使得现代编辑器(如 VS Code, PyCharm)能够提供精准的代码补全和类型检查,提升开发体验。
  8. 依赖注入系统: FastAPI 提供了一个简单但功能强大的依赖注入系统,有助于代码解耦和复用。

1.3 ASGI 与 WSGI

传统的 Python Web 框架(如 Flask, Django)大多基于 WSGI(Web 服务器网关接口)标准。WSGI 是同步的,虽然可以通过一些库实现异步,但并非原生支持。而 ASGI 是 WSGI 的精神继承者,设计之初就考虑了异步操作(如 async/await)。FastAPI 基于 ASGI,使其能够轻松处理大量并发连接和 I/O 密集型任务(如网络请求、数据库操作),从而获得更好的性能。


第二章:准备工作 —— 环境设置与安装

在开始编写代码之前,我们需要搭建好开发环境。强烈建议使用虚拟环境来隔离项目依赖。

2.1 创建虚拟环境

打开你的终端或命令行工具,进入你希望创建项目的目录,然后执行以下命令:

“`bash

创建一个名为 .venv 的虚拟环境目录 (推荐)

python -m venv .venv

激活虚拟环境

Windows (cmd.exe)

.\ .venv\Scripts\activate.bat

Windows (PowerShell)

.\ .venv\Scripts\Activate.ps1

macOS / Linux (bash/zsh)

source .venv/bin/activate
“`

激活成功后,你通常会看到命令行提示符前面出现了 (.venv) 字样。

2.2 安装 FastAPI 和 Uvicorn

FastAPI 本身是一个 Web 框架,它需要一个 ASGI 服务器来运行。Uvicorn 是一个闪电般快速的 ASGI 服务器,基于 uvloop 和 httptools 构建,是运行 FastAPI 应用的推荐选择。

在激活的虚拟环境中,使用 pip 安装 FastAPI 和 Uvicorn:

bash
pip install fastapi uvicorn[standard]

这里的 [standard] 会额外安装一些推荐的依赖,如 python-multipart(用于处理表单数据)和 websockets(如果需要 WebSocket 支持)。对于本基础教程,仅安装 fastapiuvicorn 也是可以的:

bash
pip install fastapi uvicorn

安装完成后,我们的开发环境就绪了。


第三章:“Hello, World!” —— 你的第一个 FastAPI 应用

让我们从创建一个最简单的 FastAPI 应用开始。

3.1 创建主文件

在你的项目目录下,创建一个名为 main.py 的 Python 文件。

3.2 编写第一个 API

main.py 文件中输入以下代码:

“`python

main.py

from fastapi import FastAPI

1. 创建 FastAPI 实例

app 将是与 API 交互的主要入口点

app = FastAPI()

2. 定义一个路径操作 (Path Operation) / 路由 (Route)

@app.get("/") 是一个装饰器 (Decorator),它告诉 FastAPI:

– 当收到一个针对路径 / 的 GET 请求时,

– 下面的函数 read_root 应该被调用来处理这个请求。

@app.get(“/”)
async def read_root():
# 3. 返回响应内容
# FastAPI 会自动将 Python 字典或列表转换为 JSON 响应
return {“message”: “Hello, FastAPI World!”}

4. (可选) 定义另一个路径操作

@app.get(“/about”)
async def read_about():
return {“description”: “This is a simple FastAPI application.”}
“`

代码解读:

  1. from fastapi import FastAPI:导入 FastAPI 类。
  2. app = FastAPI():创建一个 FastAPI 类的实例,变量名 app 是一个惯例,但你可以使用任何你喜欢的名字。这个实例将是创建所有 API 的主要交互点。
  3. @app.get("/"):这是一个 路径操作装饰器
    • @ 符号表示这是一个 Python 装饰器。
    • app 指的是我们上面创建的 FastAPI 实例。
    • .get 指的是这个路径操作将响应 HTTP GET 方法。FastAPI 还提供了对应其他 HTTP 方法的装饰器,如 @app.post(), @app.put(), @app.delete() 等。
    • ("/") 是这个路径操作对应的 路径(或称为路由)。这里是根路径 /
  4. async def read_root()::这是 路径操作函数
    • async def 定义了一个异步函数。在 FastAPI 中,你可以使用普通的 def 或异步的 async def。使用 async def 允许你在函数内部使用 await 来调用其他异步代码(如数据库操作、外部 API 请求),这对于提高 I/O 密集型任务的性能非常有帮助。即使你的函数不执行任何异步操作,FastAPI 也能正确处理 async def。对于初学者,可以暂时将其视为普通的函数定义。
    • read_root 是函数名,FastAPI 对函数名没有特殊要求,但一个描述性的名字有助于代码可读性。
  5. return {"message": "Hello, FastAPI World!"}:函数返回的内容将作为 API 的响应。FastAPI 非常智能,它可以自动将 Python 的 dictliststrint,甚至是 Pydantic 模型实例转换为 JSON 格式的 HTTP 响应。

3.3 运行应用

现在,回到你的终端(确保虚拟环境已激活,并且你位于包含 main.py 的目录下),使用 Uvicorn 来运行你的应用:

bash
uvicorn main:app --reload

命令解析:

  • uvicorn: 调用 Uvicorn 服务器。
  • main: 指的是你的 Python 文件名 main.py(不带 .py 后缀)。
  • app: 指的是在 main.py 文件中创建的 FastAPI 实例对象 app = FastAPI()
  • :: 分隔符,连接文件名和实例名。
  • --reload: 这是一个非常有用的选项,它会让服务器在检测到代码更改时自动重新加载。这在开发阶段非常方便,省去了每次修改代码后手动重启服务器的麻烦。

运行命令后,你应该会在终端看到类似以下的输出:

INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [xxxxx] using statreload
INFO: Started server process [xxxxx]
INFO: Waiting for application startup.
INFO: Application startup complete.

这表明你的 FastAPI 应用已经成功运行在本地的 http://127.0.0.1:8000(或 http://localhost:8000)地址上。

3.4 访问 API

现在,打开你的 Web 浏览器,访问 http://127.0.0.1:8000。你应该会看到如下 JSON 响应:

json
{
"message": "Hello, FastAPI World!"
}

接着,访问 http://127.0.0.1:8000/about,你会看到:

json
{
"description": "This is a simple FastAPI application."
}

恭喜!你已经成功创建并运行了你的第一个 FastAPI 应用!


第四章:深入路径操作 —— 参数传递

API 的核心功能之一是接收客户端传递的参数。FastAPI 提供了非常直观的方式来处理不同类型的参数。

4.1 路径参数 (Path Parameters)

路径参数是 URL 路径的一部分,用于标识特定的资源。例如,在 /items/5 中,5 就是一个路径参数,可能代表 ID 为 5 的物品。

在 FastAPI 中,你可以使用与 Python 格式化字符串相似的语法 {param_name} 来声明路径参数,并在路径操作函数的参数中接收它。

修改 main.py,添加一个新的路径操作:

“`python

main.py

from fastapi import FastAPI

app = FastAPI()

… (之前的 / 和 /about 路由) …

使用路径参数 {item_id}

@app.get(“/items/{item_id}”)
async def read_item(item_id: int): # 使用类型提示 int
# FastAPI 会自动将路径中的 item_id 转换为整数
# 如果转换失败(例如 URL 是 /items/foo),会返回 422 Unprocessable Entity 错误
return {“item_id”: item_id, “description”: f”Details for item {item_id}”}
“`

代码解读:

  • @app.get("/items/{item_id}"): 路径字符串中包含了 {item_id},这声明了一个名为 item_id 的路径参数。
  • async def read_item(item_id: int): 函数参数名 item_id 必须 与路径中声明的参数名 {item_id} 完全一致。
  • item_id: int: 这里使用了 Python 类型提示。FastAPI 利用这个类型提示:
    • 数据转换: 它会自动尝试将从 URL 中提取的路径参数(默认为字符串)转换为 int 类型。
    • 数据验证: 如果转换失败(例如用户访问 /items/abc),FastAPI 会自动返回一个清晰的 HTTP 422 错误,指示数据验证失败。

测试:

确保 Uvicorn 正在运行(如果之前停止了,用 uvicorn main:app --reload 重新启动)。

  • 访问 http://127.0.0.1:8000/items/10,你会看到:
    json
    {
    "item_id": 10,
    "description": "Details for item 10"
    }
  • 访问 http://127.0.0.1:8000/items/abc,你会看到一个 JSON 错误响应,类似:
    json
    {
    "detail": [
    {
    "loc": [
    "path",
    "item_id"
    ],
    "msg": "value is not a valid integer",
    "type": "type_error.integer"
    }
    ]
    }

    这展示了 FastAPI 基于类型提示的自动数据验证能力。

4.2 查询参数 (Query Parameters)

查询参数是 URL 中 ? 之后的部分,通常用于过滤、分页或传递可选信息。例如:http://example.com/search?query=fastapi&limit=10 中的 querylimit 就是查询参数。

在 FastAPI 中,任何没有在路径字符串中声明的函数参数,都会被自动识别为查询参数

让我们修改 /items/ 路径,让它可以接受可选的 skiplimit 查询参数用于分页:

“`python

main.py

from fastapi import FastAPI
from typing import Union # 或者在 Python 3.10+ 中使用 |

app = FastAPI()

… (之前的路由) …

模拟一个简单的数据库

fake_items_db = [{“item_name”: “Foo”}, {“item_name”: “Bar”}, {“item_name”: “Baz”}]

@app.get(“/items/”) # 注意,路径改为 /items/,不带路径参数
async def read_items(skip: int = 0, limit: int = 10):
# skip 和 limit 没有出现在路径字符串中,所以它们是查询参数
# 我们为它们提供了默认值 0 和 10
return fake_items_db[skip : skip + limit]

— 结合路径参数和查询参数 —

之前的 /items/{item_id} 路由

@app.get(“/items/{item_id}”)
async def read_item(item_id: int, q: Union[str, None] = None): # Python 3.10+ 可以写成 q: str | None = None
# item_id 是路径参数
# q 是一个可选的查询参数,类型可以是字符串或 None,默认值为 None
response = {“item_id”: item_id, “description”: f”Details for item {item_id}”}
if q:
response.update({“query_param”: q})
return response
“`

代码解读 (read_items 函数):

  • async def read_items(skip: int = 0, limit: int = 10):
    • skiplimit 没有在路径 @app.get("/items/") 中声明,因此 FastAPI 将它们视为查询参数。
    • 我们为它们指定了类型提示 int 和默认值 010。这意味着:
      • FastAPI 会尝试将 URL 中的查询参数值转换为整数。
      • 如果 URL 中没有提供这些参数(例如访问 /items/),则会使用默认值。
      • 因为有默认值,所以这两个参数是可选的。
  • return fake_items_db[skip : skip + limit]: 使用 skiplimit 对模拟数据进行切片。

代码解读 (read_item 函数更新):

  • q: Union[str, None] = None (或 q: str | None = None)**:
    • q 是一个查询参数。
    • 类型提示 Union[str, None] (或 str | None) 表示 q 的值可以是字符串,也可以是 None
    • = None 设置了默认值。这意味着如果 URL 中不包含 q 参数,q 的值将是 None,因此 q 是可选的。
  • if q:: 检查 q 是否有值(非 None 且非空字符串),如果有,则将其添加到响应中。

测试:

  • 访问 http://127.0.0.1:8000/items/ (不带参数):
    json
    [{"item_name":"Foo"},{"item_name":"Bar"},{"item_name":"Baz"}]

    (因为 limit 默认为 10,所以返回了所有 3 个)
  • 访问 http://127.0.0.1:8000/items/?skip=0&limit=2:
    json
    [{"item_name":"Foo"},{"item_name":"Bar"}]
  • 访问 http://127.0.0.1:8000/items/?skip=1:
    json
    [{"item_name":"Bar"},{"item_name":"Baz"}]

    (limit 使用默认值 10)
  • 访问 http://127.0.0.1:8000/items/5?q=somequery:
    json
    {
    "item_id": 5,
    "description": "Details for item 5",
    "query_param": "somequery"
    }
  • 访问 http://127.0.0.1:8000/items/5 (不带 q):
    json
    {
    "item_id": 5,
    "description": "Details for item 5"
    }

FastAPI 基于函数参数的声明方式(是否在路径中、是否有默认值、类型提示)来智能区分路径参数和查询参数,并进行自动的数据转换和验证。


第五章:请求体与数据模型 —— Pydantic 的力量

对于 GET 请求,参数通常通过 URL 传递。但对于需要发送数据的操作(如创建或更新资源,常用 POST、PUT、PATCH 方法),数据通常放在 请求体 (Request Body) 中发送,一般使用 JSON 格式。

FastAPI 使用 Pydantic 库来定义和验证请求体的数据结构。

5.1 Pydantic 简介

Pydantic 是一个基于 Python 类型提示进行数据验证和设置管理的库。你可以定义数据模型类,这些类的实例可以从输入数据(如 JSON)自动创建,并且在创建过程中会进行严格的类型和规则校验。

5.2 定义 Pydantic 模型

让我们创建一个用于表示 “Item” 的数据模型。在 main.py 的顶部(import 语句之后)添加以下代码:

“`python

main.py

from fastapi import FastAPI
from pydantic import BaseModel # 导入 BaseModel
from typing import Union, Optional # Optional 是 Union[X, None] 的简写

— Pydantic 模型定义 —

class Item(BaseModel):
name: str
description: Union[str, None] = None # 可选字段,默认为 None
price: float
tax: Optional[float] = None # 另一种表示可选字段的方式
“`

代码解读:

  • from pydantic import BaseModel: 导入 Pydantic 的基类 BaseModel
  • class Item(BaseModel):: 定义一个名为 Item 的类,它继承自 BaseModel。这个类就定义了我们期望接收的数据结构。
  • name: str: 定义一个名为 name 的字段,类型必须是字符串 (str)。这是一个必需字段,因为没有默认值。
  • description: Union[str, None] = None: 定义一个 description 字段,类型可以是字符串或 None,默认值为 None。这是一个可选字段。
  • price: float: 定义一个 price 字段,类型必须是浮点数 (float)。必需字段。
  • tax: Optional[float] = None: 定义一个 tax 字段,类型可以是浮点数或 None ( Optional[float] 等价于 Union[float, None] ),默认值为 None。可选字段。

Pydantic 会利用这些类型提示来验证传入的数据。

5.3 在路径操作中使用模型

现在,我们可以创建一个接收 Item 数据的路径操作,通常使用 POST 方法来创建新资源。

“`python

main.py

… (之前的 FastAPI 实例和 Pydantic 模型定义) …

app = FastAPI()

… (之前的 GET 路由) …

@app.post(“/items/”)
async def create_item(item: Item): # 将函数参数 item 的类型声明为我们定义的 Item 模型
# 当 FastAPI 看到参数类型是 Pydantic 模型时,它会:
# 1. 自动从请求体中读取 JSON 数据。
# 2. 使用 Item 模型验证数据结构和类型。
# – 如果数据无效,自动返回 422 错误。
# – 如果数据有效,创建一个 Item 类的实例,并将其赋值给 item 参数。
# 3. 你可以在函数内部像操作普通 Python 对象一样操作 item。

item_dict = item.dict() # 可以用 .dict() 方法将 Pydantic 模型转换为字典
if item.tax:
    price_with_tax = item.price + item.tax
    item_dict.update({"price_with_tax": price_with_tax})

# 通常在这里会将 item 保存到数据库...
# 为了演示,我们直接返回接收到的 item 数据(可能包含计算后的税后价格)
return item_dict

“`

代码解读:

  • @app.post("/items/"): 使用 @app.post 装饰器,表示这个路径响应 HTTP POST 请求。
  • async def create_item(item: Item):
    • 函数参数 item 的类型被声明为我们之前定义的 Pydantic 模型 Item
    • FastAPI 看到这个类型提示后,就会期望请求体中包含一个符合 Item 模型结构的 JSON 对象
    • 它会自动解析请求体中的 JSON,用 Item 模型进行验证,并将验证通过的数据实例化为 item 对象供函数使用。
  • item.dict(): Pydantic 模型实例有一个 .dict() 方法,可以方便地将其转换为 Python 字典。
  • if item.tax:: 我们可以像访问普通 Python 对象的属性一样访问 itemname, description, price, tax 属性。

5.4 测试带请求体的 POST 请求

由于浏览器通常只能方便地发送 GET 请求,测试 POST 请求(以及其他带请求体的方法如 PUT, PATCH, DELETE)的最佳方式是使用 FastAPI 自动生成的交互式文档,或者使用 curl、Postman、Insomnia 等 HTTP 客户端工具。

使用 FastAPI 自动文档 (推荐):

  1. 确保 Uvicorn 服务器正在运行 (uvicorn main:app --reload)。
  2. 在浏览器中访问 http://127.0.0.1:8000/docs。你会看到 Swagger UI 界面。
  3. 找到 POST /items/ 这个路径操作,点击它展开。
  4. 点击右上角的 “Try it out” 按钮。
  5. 你会看到一个 “Request body” 输入框,里面已经根据 Item 模型生成了一个 JSON 模板:
    json
    {
    "name": "string",
    "description": "string",
    "price": 0,
    "tax": 0
    }

    注意:这里的 descriptiontax 显示为 "string"0 只是示例,你可以修改它们,或者完全删除可选字段。
  6. 修改 JSON 数据,例如:
    json
    {
    "name": "Super Widget",
    "description": "A very useful widget",
    "price": 19.99,
    "tax": 1.99
    }

    或者只包含必需字段:
    json
    {
    "name": "Basic Gadget",
    "price": 9.50
    }
  7. 点击下方的 “Execute” 按钮。
  8. 向下滚动,你会看到服务器的响应。
    • 如果你的 JSON 数据有效,你会看到类似 200 OK 的响应,响应体包含你发送的数据以及可能的 price_with_tax
      json
      {
      "name": "Super Widget",
      "description": "A very useful widget",
      "price": 19.99,
      "tax": 1.99,
      "price_with_tax": 21.98
      }
    • 如果你发送了无效的数据(例如,price 是字符串 "expensive",或者缺少必需的 name 字段),你会看到 422 Unprocessable Entity 错误响应,其中详细说明了哪个字段以及为什么无效。

这种自动文档和交互式测试能力是 FastAPI 的巨大优势,极大地简化了 API 的开发、调试和协作流程。


第六章:自动交互式 API 文档

正如上一节所体验到的,FastAPI 最令人称道的特性之一就是其开箱即用的自动 API 文档。

在你运行 FastAPI 应用后,可以通过两个不同的 URL 访问自动生成的文档:

  1. Swagger UI: 访问 /docs (例如 http://127.0.0.1:8000/docs)。这是一个功能丰富的交互式界面,允许你浏览所有 API 端点、查看它们的参数(路径、查询、请求体)、预期的响应格式,并直接在浏览器中发送请求进行测试。
  2. ReDoc: 访问 /redoc (例如 http://127.0.0.1:8000/redoc)。这是一个侧重于展示的文档界面,提供了另一种清晰、美观的方式来查看 API 的结构和模式,但通常不直接提供交互测试功能。

文档是如何生成的?

FastAPI 检查你的代码:

  • 路径操作装饰器 (@app.get, @app.post 等) 和路径字符串 (/items/{item_id})。
  • 路径操作函数的参数,包括它们的名称和 类型提示 (如 item_id: int, q: str | None = None)。
  • Pydantic 模型 (class Item(BaseModel): ...),用于定义请求体和响应体的数据结构。

基于这些信息,FastAPI 自动生成符合 OpenAPI 标准的 JSON Schema。OpenAPI 是一个定义 RESTful API 的规范。然后,FastAPI 使用这个 Schema 来驱动 Swagger UI 和 ReDoc 这两个 Web 界面。

这意味着,你只需要编写 Python 代码,使用标准的类型提示和 Pydantic 模型,就能免费获得最新、准确且可交互的 API 文档。当你修改代码(例如添加新路由、更改参数类型、更新模型字段)并重新加载应用后,文档也会自动更新。

这不仅方便了后端开发者自己测试,也极大地便利了前端开发者、测试工程师以及任何需要使用这个 API 的人。


第七章:更进一步 —— 数据验证增强

我们已经看到 FastAPI 和 Pydantic 如何通过类型提示进行基础的数据验证。Pydantic 还允许我们添加更复杂的验证规则。

7.1 使用 Field 添加验证和元数据

我们可以从 Pydantic 导入 Field,并将其用作模型字段的默认值,来添加额外的验证约束和元数据(如描述、示例等)。

修改 Item 模型:

“`python

main.py

from fastapi import FastAPI, Path, Query # 导入 Path 和 Query
from pydantic import BaseModel, Field # 导入 Field
from typing import Union, Optional, List # 导入 List

… (Item 模型定义) …

class Item(BaseModel):
name: str = Field(…, title=”Item Name”, max_length=50, example=”Super Widget”) # … 表示必需字段
description: Union[str, None] = Field(
default=None, title=”Item Description”, max_length=300, example=”A very useful widget”
)
price: float = Field(…, gt=0, description=”The price must be greater than zero”, example=19.99) # gt = greater than
tax: Optional[float] = Field(default=None, ge=0, description=”Tax rate, must be non-negative”, example=1.99) # ge = greater than or equal

更新路径操作以使用 Query 和 Path 进行参数验证

@app.get(“/items_validated/”)
async def read_items_validated(
q: Optional[str] = Query(
default=None,
title=”Query string”,
description=”Optional query string to search items”,
min_length=3,
max_length=50,
regex=”^fixedquery$” # 示例:要求 q 必须是 “fixedquery”
),
limit: int = Query(default=10, ge=1, le=100) # ge >= 1, le <= 100
):
results = {“items”: [{“item_id”: “Foo”}, {“item_id”: “Bar”}]}
if q:
results.update({“q”: q})
# 实际应用中会根据 limit 处理返回数量
results.update({“limit”: limit})
return results

@app.get(“/items_validated/{item_id}”)
async def read_item_validated(
item_id: int = Path(…, title=”The ID of the item to get”, ge=1), # ge >= 1, … 表示必需
q: Optional[str] = Query(default=None, max_length=50) # 对查询参数也可用 Query
):
return {“item_id”: item_id, “q”: q}

“`

代码解读:

  • from pydantic import Field: 导入 Field 函数。
  • name: str = Field(..., max_length=50):
    • Field(...) 的第一个参数 ... (Python 的 Ellipsis 对象) 表示这个字段是必需的。如果你想提供默认值,可以替换 ...,例如 Field(default="Default Name", max_length=50)
    • title, description, example 用于在 OpenAPI 文档中提供更丰富的信息。
    • max_length=50 添加了一个验证规则:name 的长度不能超过 50 个字符。
  • price: float = Field(..., gt=0): gt=0 表示 price 的值必须大于 0。还有 ge (大于等于), lt (小于), le (小于等于) 等。
  • from fastapi import Query, Path: 导入 QueryPath,它们的作用类似于 Pydantic 的 Field,但专门用于查询参数和路径参数,允许添加验证和元数据。
  • q: Optional[str] = Query(default=None, min_length=3, regex="^fixedquery$"): 对查询参数 q 添加了最小长度和正则表达式验证。
  • limit: int = Query(default=10, ge=1, le=100): 限制 limit 参数在 1 到 100 之间。
  • item_id: int = Path(..., title="...", ge=1): 对路径参数 item_id 要求其必须大于等于 1。

现在,如果你在 /docs 中测试 POST /items/,或者访问 /items_validated//items_validated/{item_id} 时提供了不符合这些新规则的数据,FastAPI 会自动返回 422 错误,并清晰地指出哪个字段违反了哪个规则。同时,文档中也会显示这些约束和描述信息。


第八章:总结与后续步骤

在本教程中,我们从零开始,一步步探索了 FastAPI 的基础知识:

  1. 理解了 FastAPI 的核心优势:高性能、快速开发、自动文档、基于类型提示的验证等。
  2. 搭建了开发环境:创建虚拟环境并安装了 FastAPI 和 Uvicorn。
  3. 创建了第一个 FastAPI 应用:使用 FastAPI() 实例和 @app.get() 等路径操作装饰器。
  4. 学会了运行应用:使用 uvicorn main:app --reload
  5. 掌握了处理参数的方法:区分并使用了路径参数和查询参数,利用类型提示进行自动转换和验证。
  6. 学习了处理请求体:通过定义 Pydantic 模型 (BaseModel) 来接收和验证 JSON 请求体。
  7. 体验了自动交互式文档:利用 /docs (Swagger UI) 和 /redoc (ReDoc) 进行 API 浏览和测试。
  8. 了解了更深入的数据验证:使用 Pydantic 的 Field 以及 FastAPI 的 QueryPath 添加更复杂的验证规则和元数据。

你现在已经掌握了使用 FastAPI 构建基本 API 的核心技能。FastAPI 的功能远不止于此,以下是一些你可以继续探索的方向:

  • 依赖注入 (Dependencies): FastAPI 强大的依赖注入系统,用于代码复用、处理认证授权、数据库连接等。
  • 响应模型 (Response Model): 控制和验证 API 的响应数据结构。
  • 表单数据 (Form Data): 处理 HTML 表单提交的数据。
  • 文件上传 (File Uploads): 处理上传的文件。
  • Cookies 和 Headers: 处理请求和响应中的 Cookies 和 Headers。
  • 中间件 (Middleware): 在请求处理流程中添加全局逻辑(如日志记录、性能监控)。
  • 异步操作 (async/await): 更深入地理解和利用 Python 的异步特性来提升性能。
  • 数据库集成: 将 FastAPI 与 ORM (如 SQLAlchemy, Tortoise ORM) 或 ODM (如 Motor, Beanie) 结合使用。
  • 认证与授权 (Authentication & Authorization): 使用 OAuth2、JWT 等实现用户认证和权限控制。
  • 测试 (Testing): 编写单元测试和集成测试来确保 API 的正确性。
  • 部署 (Deployment): 将你的 FastAPI 应用部署到服务器或云平台。

FastAPI 官方文档 (fastapi.tiangolo.com) 是非常优秀的学习资源,包含了大量示例和详细解释。

构建 API 是一个实践性很强的过程。现在,尝试基于今天所学,构思一个小项目(例如一个简单的待办事项列表 API、一个博客文章管理 API),并动手实现它。在实践中你会遇到更多问题,解决问题的过程就是最好的学习。

祝贺你完成了 FastAPI 的入门之旅!希望这个现代、高效的框架能为你的 Web 开发工作带来便利和乐趣。继续探索,不断进步!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部