FastAPI 路径操作配置详解:用装饰器参数声明状态码、标签与接口元数据
路径操作配置(Path Operation Configuration)是 FastAPI 用来自动生成 OpenAPI 文档与交互式 API 界面的关键机制。本文将聚焦于在 @app.get()、@app.post() 等路径操作装饰器上直接传入的 status_code、tags、summary、description、response_description 与 deprecated 等参数,逐一结合本仓库中的示例代码与源码实现,说明这些参数如何被写入 OpenAPI schema、如何影响 Swagger UI 的展示效果,帮助你为自己的接口声明准确、完整且可维护的元数据。
参数传给装饰器,而不是传给函数
使用这些配置参数前,必须牢记一个重要的前提:它们全部是装饰器的参数,与路径操作函数(async def / def)本身的入参毫无关系。也就是说,它们描述的是“这个 HTTP 接口长什么样”,而不是“接口如何接收请求数据”。
@app.post("/items/", status_code=status.HTTP_201_CREATED) # 传给装饰器
async def create_item(item: Item) -> Item: # 括号里是函数自身的参数
return item
从源码结构看,FastAPI 在注册路由时会把装饰器收到的这些元数据原样保存到路由对象 APIRoute 上(见 fastapi/routing.py),后续生成 OpenAPI 时再逐项取出。本文后续每个小节,都会把“装饰器参数 → 路由对象 → OpenAPI 字段 → 文档界面效果”这条链路讲透。
设置响应状态码:status_code
用 status_code 可以显式声明路径操作返回的 HTTP 状态码。它有两个作用:一是实际响应会带上该状态码,二是它会写入 OpenAPI schema,成为文档中该响应的标识。
直接传整数,或使用 status 常量
可以直接传 int,例如 404;但如果记不住每个数字的含义,更推荐使用 status 模块里语义化命名的常量:
from fastapi import FastAPI, status
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: set[str] = set()
@app.post("/items/", status_code=status.HTTP_201_CREATED)
async def create_item(item: Item) -> Item:
return item
上面的完整示例位于 docs_src/path_operation_configuration/tutorial001_py310.py,含义是“创建成功后返回 201 Created”,语义一目了然。常见的常量还包括 status.HTTP_200_OK、status.HTTP_204_NO_CONTENT、status.HTTP_400_BAD_REQUEST、status.HTTP_404_NOT_FOUND、status.HTTP_500_INTERNAL_SERVER_ERROR 等,均可直接使用。
技术细节:fastapi.status 就是 Starlette 的 status
你也可以写 from starlette import status。事实上,FastAPI 提供的 fastapi.status 与 starlette.status 是同一个东西——前者只是为开发者提供的便捷导出,常量本身来自 Starlette。
源码层面还有一个容易被忽略的细节:在路由注册时,若传入的状态码是 IntEnum(例如某些常量以枚举形式定义),FastAPI 会先通过 int() 将其转换为普通整数再保存(见 fastapi/routing.py);若没有显式传入 status_code,生成 OpenAPI 时则会从默认响应类的 status_code 默认值中推导(通常为 200,对应逻辑在 fastapi/openapi/utils.py)。
用 tags 为接口分组
当接口数量增多,把相关路径操作归入同一“标签”会让文档结构清晰很多。给路径操作传 tags,参数类型是 list[str](通常只放一个字符串):
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: set[str] = set()
@app.post("/items/", tags=["items"])
async def create_item(item: Item) -> Item:
return item
@app.get("/items/", tags=["items"])
async def read_items():
return [{"name": "Foo", "price": 42}]
@app.get("/users/", tags=["users"])
async def read_users():
return [{"username": "johndoe"}]
完整示例见 docs_src/path_operation_configuration/tutorial002_py310.py。三个接口分别归属 items、users 两个标签。标签会被加入 OpenAPI schema,并由自动文档界面用于分组展示——在 Swagger UI 中,属于 items 的接口会折叠在 items 分组下、属于 users 的接口折叠在 users 分组下:
从源码看,生成 OpenAPI 时只要路由上有 tags,get_openapi_operation_metadata() 就会直接把它写入 operation["tags"](见 fastapi/openapi/utils.py)。
用 Enum 统一管理标签
在大型应用里,标签会越积越多,而且很容易出现“同一个分组用词不一致”的情况(比如有时写 items、有时写 item)。此时把标签放进一个 Enum 集中管理是更稳妥的做法——FastAPI 对枚举标签的支持与纯字符串完全一致:
from enum import Enum
from fastapi import FastAPI
app = FastAPI()
class Tags(Enum):
items = "items"
users = "users"
@app.get("/items/", tags=[Tags.items])
async def get_items():
return ["Portal gun", "Plumbus"]
@app.get("/users/", tags=[Tags.users])
async def read_users():
return ["Rick", "Morty"]
完整示例见 docs_src/path_operation_configuration/tutorial002b_py310.py。将 Tags 集中定义后,每个路径操作都引用 Tags.items、Tags.users 这样的成员,彻底避免手写字符串造成的拼写漂移。枚举成员的 value(此处即字符串 "items"、"users")最终会出现在 OpenAPI 与文档界面中,保证分组名全局唯一、始终一致。
声明接口的 summary 与 description
summary 是显示在文档中的接口短标题,description 则是更详细的说明文字。两者都可以直接作为装饰器参数传入:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: set[str] = set()
@app.post(
"/items/",
summary="Create an item",
description="Create an item with all the information, name, description, price, tax and a set of unique tags",
)
async def create_item(item: Item) -> Item:
return item
完整示例见 docs_src/path_operation_configuration/tutorial003_py310.py。
源码里对 summary 还有一个“兜底”行为值得了解:如果未显式提供,OpenAPI 的 summary 会由路由对象的函数名推导生成——将函数名中的下划线替换为空格并转为标题格式(generate_operation_summary() 的逻辑见 fastapi/openapi/utils.py)。也就是说,好的函数命名(如 create_item)即使不写 summary,也能得到尚可阅读的默认标题;但为了对外 API 文档的准确性,仍建议显式声明。
用函数 docstring 书写多行 Markdown 描述
description 往往很长、需要跨多行。为此 FastAPI 提供了更顺手的写法:直接把多行说明写进路径操作函数的 docstring,FastAPI 会自动把它读取为接口描述。docstring 支持 Markdown 语法,会按 Markdown 渲染展示,且能正确处理 docstring 缩进:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: set[str] = set()
@app.post("/items/", summary="Create an item")
async def create_item(item: Item) -> Item:
"""
Create an item with all the information:
- **name**: each item must have a name
- **description**: a long description
- **price**: required
- **tax**: if the item doesn't have tax, you can omit this
- **tags**: a set of unique tag strings for this item
"""
return item
完整示例见 docs_src/path_operation_configuration/tutorial004_py310.py。
源码实现里这一步发生在路由构造阶段:如果装饰器没有显式提供 description,FastAPI 会用 inspect.cleandoc() 处理函数 docstring(自动去除统一的缩进、清理首尾空行)作为描述,随后再进一步裁剪内容(见 fastapi/routing.py)。正因如此,docstring 内部的 Markdown 列表、粗体等格式都能被保留并正确渲染:
顺带提醒:docstring 描述也会进入 OpenAPI schema 的 description 字段,因此同样会展示在 ReDoc 等其他遵循该规范的文档工具中。
用 response_description 描述响应本身
response_description 用于描述响应。它和 description 的区别要分清:
description:描述整个路径操作(接口是做什么的、怎么用);response_description:只描述响应(成功时返回什么内容)。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
tags: set[str] = set()
@app.post(
"/items/",
summary="Create an item",
response_description="The created item",
)
async def create_item(item: Item) -> Item:
"""
Create an item with all the information:
- **name**: each item must have a name
- **description**: a long description
- **price**: required
- **tax**: if the item doesn't have tax, you can omit this
- **tags**: a set of unique tag strings for this item
"""
return item
完整示例见 docs_src/path_operation_configuration/tutorial005_py310.py。
这里有一个重要的“隐含约定”:OpenAPI 规范要求每个路径操作都必须给出响应描述。因此,如果你没有提供 response_description,FastAPI 会自动生成默认值 "Successful response"。这一点从路由对象的初始化可以确认——response_description 的默认值即 "Successful Response"(见 fastapi/routing.py),而在生成 OpenAPI 响应时,它会被写入 responses[<状态码>]["description"](见 fastapi/openapi/utils.py)。想为文档提供更有信息量的语义,就应像示例那样主动传参,而不是依赖默认文案。
标记 deprecated,优雅地废弃旧接口
当某个接口已过时、又不希望立即删除时(例如仍被老客户端调用),可以用 deprecated=True 把它标记为“已弃用”:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/", tags=["items"])
async def read_items():
return [{"name": "Foo", "price": 42}]
@app.get("/users/", tags=["users"])
async def read_users():
return [{"username": "johndoe"}]
@app.get("/elements/", tags=["items"], deprecated=True)
async def read_elements():
return [{"item_id": "Foo"}]
完整示例见 docs_src/path_operation_configuration/tutorial006_py310.py。被标记后,文档界面上该接口会明确呈现“Deprecated”状态——通常表现为整块变灰并带 Warning: Deprecated 提示:
把被弃用的 GET /elements/ 与正常的 GET /items/ 并列查看时,对比尤其明显:正常接口颜色饱满、可正常展开调用,弃用接口则整体灰化。与此同时,源码中 route.deprecated 会被映射为 OpenAPI 的 operation["deprecated"] 字段(见 fastapi/openapi/utils.py),因此该信息不只是界面装饰,而是被正式写进 schema,客户端代码生成器等工具也能据此感知接口的废弃状态。
小结与验证方式
把装饰器级元数据配置组合起来,一个信息完备的路径操作大致会长这样:
@app.post(
"/items/",
tags=[Tags.items],
summary="Create an item",
response_description="The created item",
status_code=status.HTTP_201_CREATED,
deprecated=False,
)
async def create_item(item: Item) -> Item: ...
status_code:声明响应状态码,会作用于实际响应并被写入 OpenAPI;tags/tags+Enum:统一为接口分组,驱动交互式文档的折叠结构;summary、description(或函数 docstring):定义接口的标题与完整说明;response_description:单独描述响应语义,缺省时 FastAPI 自动填充"Successful response";deprecated:把旧接口标记为废弃而不删除,文档与 schema 同步呈现。
所有配置都是“纯声明式”的——你只需把这些参数传给路径操作装饰器,FastAPI 就会负责把它们落到实际 HTTP 响应与自动生成的 OpenAPI schema(/openapi.json)中,并在 Swagger UI(/docs)与 ReDoc(/redoc)里正确呈现。
如果你想把上述参数的字段级细节进一步打磨(例如手动覆盖 OpenAPI 中的 operationId 或 deprecated 之类的字段),仓库还提供了进阶主题 path_operation_advanced_configuration 与全局元数据 metadata 的对应示例可供继续阅读。对本文六个示例,本仓库的 tests/test_tutorial/test_path_operation_configurations/ 目录下提供了 test_tutorial001.py 至 test_tutorial006.py(含 test_tutorial002b.py、合并了 003/004 的 test_tutorial003_tutorial004.py)等一一对应的测试用例,你可以通过运行这些测试直接验证各项配置在真实路由与 OpenAPI 输出中的行为是否符合预期。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00


