FastAPI 高频实用技巧指南:响应数据安全过滤、JSON 编码与 OpenAPI 文档定制
2026/9/8 20:59:09 网站建设 项目流程

FastAPI 高频实用技巧指南:响应数据安全过滤、JSON 编码与 OpenAPI 文档定制

【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi

General - How To - Recipes(西班牙语版) 与 英语原文 是 FastAPI 文档「How-To」部分的入口页之一:它不像逐章教程那样系统推进,而是把开发中最常遇到的十类问题(如何过滤返回数据、如何优化响应性能、如何为接口打标签、如何定制自动文档等)整理成一条条独立可用的「菜谱」,并精确指向文档中对应的深入章节。本指南将以这份菜谱清单为骨架,结合仓库内的可运行示例(docs_src/)与核心源码(fastapi/),逐一展开每个技巧的原理、完整代码与底层依据,让你拿到一份可直接照着做的实战手册。

阅读完整篇文章后,你将能够:用response_model/返回类型声明保证“只返回该返回的字段”,在 Pydantic(Rust 内核)序列化层面优化 JSON 响应性能,用装饰器参数为路径操作添加标签、摘要、响应说明与弃用标记,把任意数据一键转成 JSON 兼容结构,并自由定制 OpenAPI 的元数据、Schema URL 与两套文档界面(Swagger UI / ReDoc)的地址。

菜谱地图:这篇文章对应仓库中的哪些内容

菜谱(原文标题)文章小节深入文档可运行源码
Filtrar Datos - Seguridad数据安全过滤response-model.mddocs_src/response_model/
Optimizar el Rendimiento del Response性能优化与 Rust 侧序列化response-model.mddocs_src/response_model/
Etiquetas de DocumentaciónOpenAPI 标签(tags)path-operation-configuration.md#tagsdocs_src/path_operation_configuration/tutorial002_py310.py
Resumen y Descripción摘要与描述(summary/description)path-operation-configuration.mddocs_src/path_operation_configuration/tutorial003_py310.py
Descripción del Response响应描述(response_description)path-operation-configuration.mddocs_src/path_operation_configuration/tutorial005_py310.py
Deprecación弃用标记(deprecated)path-operation-configuration.mddocs_src/path_operation_configuration/tutorial006_py310.py
Convertir Datos a JSON-compatibleJSON 兼容编码器encoder.mddocs_src/encoder/tutorial001_py310.py
Metadatos OpenAPIOpenAPI 元数据定制metadata.mddocs_src/metadata/
URL Personalizada de OpenAPIOpenAPI URL 定制与禁用metadata.md#openapi-urldocs_src/metadata/tutorial002_py310.py
URLs de Documentación文档界面 URL 定制metadata.md#docs-urlsdocs_src/metadata/tutorial003_py310.py

这些菜谱彼此相对独立,按需取用即可,不必一次全部读完。需要系统学习时,可以按章节阅读 Tutorial - User Guide,或查看整个 How-To 目录的说明入口 index.md。

数据安全过滤:用好 response_model 防止返回多余数据

菜谱原文的第一条提醒是:确保你不会返回超出预期的数据。这是 Web API 最常踩的坑之一——比如返回体里夹带了用户密码、内部 ID 或数据库中多余的列。

声明返回类型的基础收益

给路径操作函数标注返回类型注解(与请求参数使用同一种方式),可以声明 Pydantic 模型、listdictintbool等任意类型。见示例 tutorial001_01_py310.py。FastAPI 会据此:

  • 校验返回数据:若字段缺失或形状不符,说明是应用自身代码的 bug,会返回服务器错误而不是“错误形状的正确数据”,客户端可以确信收到符合预期的数据;
  • 在 OpenAPI 中为响应生成JSON Schema,供自动文档与客户端代码生成工具使用;
  • 序列化返回数据为 JSON(见下节“性能优化”);
  • 最关键的是:限制并过滤输出数据到返回类型声明的范围——这正是安全性的来源。

什么时候用response_model而不是返回类型

如果你希望“函数内返回一个字典或数据库对象,但对外声明成一个 Pydantic 模型”,直接用返回类型注解会让编辑器和 mypy 报错(函数确实返回了与声明不一致的类型)。此时应改用路径操作装饰器参数response_model,它可用于@app.get()@app.post()@app.put()@app.delete()等任意操作。注意:response_model是装饰器方法(get/post)的参数,不是你的路径操作函数的参数。

若同时声明返回类型与response_modelresponse_model优先。因此你可以既保留正确的类型注解以取悦编辑器/mypy,又让 FastAPI 按response_model完成数据文档、校验与过滤。如果某些注解不是合法的 Pydantic 字段(例如返回Responsedict的联合类型会直接报错),可以用response_model=None为这条路径操作关闭响应模型生成。

经典防泄露示例:输入模型与输出模型分离

用同一个模型做输入输出是危险的。参考 tutorial002_py310.py:UserInpassword字段,创建用户接口把它原样返回,等于把明文密码送回给每个客户端。

正确做法是拆成两个模型(tutorial003_py310.py):

from typing import Any from fastapi import FastAPI from pydantic import BaseModel, EmailStr app = FastAPI() class UserIn(BaseModel): username: str password: str email: EmailStr full_name: str | None = None class UserOut(BaseModel): username: str email: EmailStr full_name: str | None = None @app.post("/user/", response_model=UserOut) async def create_user(user: UserIn) -> Any: return user # 内部返回的是含 password 的 UserIn

这里即使函数实际返回的是包含密码的UserIn,因为声明了response_model=UserOut,FastAPI 会用 Pydantic 过滤掉所有未在输出模型中声明的字段,密码永远不会进入响应。EmailStr需要先安装email-validatoruv add email-validatoruv add "pydantic[email]"

用继承兼得类型检查与数据过滤

上面的写法让函数丢掉了“返回类型正确”的编辑器支持。大多数“只需过滤掉部分字段”的场景可以用类继承解决(tutorial003_01_py310.py):定义BaseUser承载基础字段,UserIn(BaseUser)追加password,并把函数返回类型注解为BaseUser。类型系统认为UserInBaseUser的子类、注解合法,编辑器/mypy 不会抱怨;而 FastAPI 过滤返回数据时不会套用继承规则,仍然只保留返回类型声明的字段。这样“类型注解的工具链支持”与“数据过滤”两者兼得。

编码参数:控制默认值是否进入响应

当模型字段带默认值(如tax: float = 10.5tags: List[str] = []),而数据并未真正存储这些值时,可能不希望响应被长长的默认值撑满。可在装饰器上设置:

  • response_model_exclude_unset=True:只包含真正被显式赋值的字段(默认值不算);
  • response_model_exclude_defaults=True:排除取值等于默认值的字段;
  • response_model_exclude_none=True:排除值为None的字段。

这里有个值得注意的细节(对应仓库测试与文档说明):如果数据显式设置了与默认值相同的值(比如显式传了tax=10.5),Pydantic 仍会保留它,因为“显式赋值”与“取默认值”是两种状态。

另外response_model_includeresponse_model_exclude可接收一个set/listlist会被自动转成set)来快速裁切字段。但官方更推荐用“多类 + 返回类型”方案,因为include/exclude并不会改变 OpenAPI 中生成的完整模型 Schema,同理response_model_by_alias也适用这一提醒。

响应性能优化:Pydantic Rust 内核完成 JSON 序列化

菜谱的第二条提示面向性能:返回 JSON 时使用返回类型或response_model。原因是 Pydantic v2 的序列化核心用 Rust 实现(pydantic-core),FastAPI 会借助 Pydantic 在 Rust 侧完成向 JSON 数据的序列化转换,而不必在 Python 侧逐字段手工拼接。声明响应模型的同时,校验、文档与过滤也随之免费获得。

这也解释了为什么要尽量“用类型声明响应”而不是裸返回dict:显式类型让 FastAPI 能跳过不确定的运行时猜测路径,把序列化交给经过充分优化的 Pydantic 管线处理。仓库中大量相关测试(如 tests/test_serialize_response.py、tests/test_serialize_response_model.py)都在回归验证“模型声明下响应被正确序列化与裁剪”的行为。

为路径操作添加 OpenAPI 标签(tags)

为了让自动文档按业务域分组,可以在路径操作装饰器上传入tags参数(一个str列表,通常只有一个字符串)。完整的对照示例见 tutorial002_py310.py:

@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"}]

这些标签会进入 OpenAPI Schema,并在 Swagger UI / ReDoc 界面中把属于同一标签的接口聚合到一组。需要保证标签拼写一致时,可以把标签放进Enum(见 tutorial002b_py310.py),与普通字符串用法完全相同。

为路径操作添加摘要与描述

通过装饰器参数summarydescription可以为路径操作添加说明文字(示例 tutorial003_py310.py):

@app.post( "/items/", summary="Create an item", description="Create an item with all the information", ) async def create_item(item: Item) -> Item: return item

描述通常较长、跨多行,官方更推荐直接写在路径操作函数的docstring里(见 tutorial004_py310.py):docstring 支持 Markdown 语法,FastAPI 会自动读取并正确渲染(会考虑缩进)。示例中使用- **name**: ...这样的列表/加粗写法,最终会在交互文档中显示成带格式的富文本。

为响应单独编写描述(response_description)

response_description描述的是响应本身,而description描述的是整个路径操作——两者语义不同,不要把两者混用。OpenAPI 规范要求每条路径操作都必须有响应描述;若你未提供,FastAPI 会自动补一条 “Successful response”。

用法示例(tutorial005_py310.py):

@app.post( "/items/", summary="Create an item", response_description="The created item", ) async def create_item(item: Item) -> Item: return item

标记路径操作已弃用(deprecated)

在接口需要“标记废弃但不删除”时,传入布尔参数deprecated=True(示例 tutorial006_py310.py):

@app.get("/elements/", tags=["items"], deprecated=True) async def read_elements(): return [{"item_id": "Foo"}]

文档界面会以明显的视觉样式区分 deprecated 与非 deprecated 的接口,同时该标记也会写入 OpenAPI Schema,提醒下游调用方及时迁移。

以上路径操作配置的装饰器参数(状态码、标签、摘要、描述、响应描述、弃用等)都直接传给装饰器,而不是传给路径操作函数,这是阅读源码时最容易误解的一点;仓库测试 tests/test_operations_signatures.py 等对这类参数签名做了约束验证。

把任意数据转换为 JSON 兼容结构:jsonable_encoder

datetime对象、Pydantic 模型这类数据无法直接被 Python 标准json编码,也不适合直接存入只接受 JSON 兼容数据的存储层。FastAPI 提供的jsonable_encoder()专门解决这个问题:它接收任意对象,返回一个值及子值全部 JSON 兼容的标准 Python 结构(如dict/list),可直接交给json.dumps()或塞进数据库。

注意它的返回并不是一个大的 JSON 字符串,而是结构化的 Python 容器。官方用例(tutorial001_py310.py):

from datetime import datetime from fastapi import FastAPI from fastapi.encoders import jsonable_encoder from pydantic import BaseModel fake_db = {} class Item(BaseModel): title: str timestamp: datetime description: str | None = None app = FastAPI() @app.put("/items/{id}") def update_item(id: str, item: Item): json_compatible_item_data = jsonable_encoder(item) fake_db[id] = json_compatible_item_data

本例中Item被转成dict,其中的datetime被转成 ISO 8601 格式字符串,之后就能安全存入fake_db。函数实现在 fastapi/encoders.py,FastAPI 内部也正是用它对数据进行编码,所以这条菜谱不仅适用于存储,也解释了 FastAPI 响应处理管线中的一环。

定制 OpenAPI 顶层元数据(title/version/contact/license 等)

在创建FastAPI()实例时,可以设置以下会进入 OpenAPI 规范并呈现在文档界面中的字段(完整示例 tutorial001_py310.py):

参数类型说明
titlestrAPI 的标题
summarystrAPI 的简短概述(OpenAPI 3.1.0 / FastAPI 0.99.0 起支持)
descriptionstrAPI 的描述,支持 Markdown
versionstr你自己应用的版本号,例如2.5.0(不是 OpenAPI 的版本)
terms_of_servicestr服务条款 URL,必须是合法 URL
contactdict联系信息,可含name(联系人/组织名)、url(联系信息 URL)、email(合法邮箱)
license_infodict许可证信息:name(必填,一旦设置license_info则必须提供)、url或 OpenAPI 3.1.0 起新增的identifier(SPDX 许可证表达式,与url互斥)

典型写法:

app = FastAPI( title="ChimichangApp", description="ChimichangApp API helps you do awesome stuff. 🚀\n\n## Items\n\nYou can **read items**.", summary="Deadpool's favorite app. Nuff said.", version="0.0.1", terms_of_service="http://example.com/terms/", contact={ "name": "Deadpoolio the Amazing", "url": "http://x-force.example.com/contact/", "email": "dp@x-force.example.com", }, license_info={ "name": "Apache 2.0", "url": "https://www.apache.org/licenses/LICENSE-2.0.html", }, )

使用 SPDXidentifier的写法可参考 tutorial001_1_py310.py。若想让description中的 Markdown 正常渲染,直接写即可,文档界面会按 Markdown 处理。

标签级元数据:openapi_tags

除了顶层元数据,还能用openapi_tags为文档分组补充说明(示例 tutorial004_py310.py)。它接收一个列表,每个元素是对应一个标签的字典:

  • name(必填):与你路径操作/APIRoutertags使用的标签名一致;
  • description:标签说明,支持 Markdown;
  • externalDocs:外部文档字典,含description与必填的url

列表里字典的顺序决定标签在文档界面的展示顺序(可以覆盖字母序)。你不必为所有用到的标签都补充元数据。

定制(或禁用)OpenAPI URL

默认 OpenAPI Schema 服务在/openapi.json。通过openapi_url参数可以改地址,例如放到/api/v1/openapi.json(示例 tutorial002_py310.py):

app = FastAPI(openapi_url="/api/v1/openapi.json")

若想彻底关闭 OpenAPI,将其设为openapi_url=None,依赖它的文档界面也会一并停用。从 fastapi/applications.py 的参数文档可以看到该参数的默认值即"/openapi.json",且仅当openapi_url非空时应用才会注册对应路由与docs/redoc界面(相关逻辑位于 fastapi/applications.py)。

如果场景更复杂(例如希望依据环境变量条件性地开/关文档),可参考 conditional-openapi.md 中“用 Pydantic Settings 配置 OpenAPI”的做法,并结合 conditional_openapi/tutorial001_py310.py。需要提醒的是:隐藏生产环境的文档界面不应成为保护 API 的手段——接口本身仍然可达,安全缺陷依然存在,这更接近“通过隐匿实现安全”。正确的加固方向是:明确定义 Pydantic 模型、用依赖实现权限与角色控制、绝不存储明文密码、采用成熟的密码哈希与 JWT 等方案、必要时用 OAuth2 scopes 细化权限。

定制文档界面的 URL:docs_url 与 redoc_url

FastAPI 内置两套自动文档界面,均可独立定制或禁用:

  • Swagger UI:默认在/docs,用docs_url改地址,设docs_url=None禁用;
  • ReDoc:默认在/redoc,用redoc_url改地址,设redoc_url=None禁用。

例如把 Swagger UI 放到/documentation并停用 ReDoc(示例 tutorial003_py310.py):

app = FastAPI(docs_url="/documentation", redoc_url=None)

这两个参数在 fastapi/applications.py 中均有详细注解:若openapi_url设为None,两者会自动随之禁用。测试层面,仓库在 tests/test_application.py、tests/test_custom_swagger_ui_redirect.py 等文件中对这些 URL 的注册与重定向行为做了完整验证。

小结与建议

对照这份 FastAPI 官方 “General How-To Recipes” 清单,可以沉淀出几条立即可用的开发习惯:

  1. 永远声明响应形状(返回类型或response_model),让 FastAPI/Pydantic 过滤数据、生成 Schema 并加速序列化,输出模型与输入模型分离是防止密码等敏感字段外泄的第一道闸门;
  2. 装饰器参数是文档化的主入口tagssummarydescriptionresponse_descriptiondeprecated全部作用于“整条路径操作”,应在装饰器上传参而非函数体内;
  3. 面向存储的 JSON 转换统一走jsonable_encoder,不要手工处理datetime等类型;
  4. 应用元数据与文档地址FastAPI()实例化时一次性声明,可用环境变量与 Settings 驱动条件开关,但不要指望“关掉文档”来保障 API 安全。

文中每个示例的完整可运行源码都在仓库docs_src/相应目录下,对应主题的逐章讲解见 Tutorial 目录;需要进一步了解其他“如何做”型话题(认证错误码、条件化 OpenAPI、自定义文档资源、Pydantic v1 迁移等)时,可以直接浏览整个 How-To 目录。

【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询