ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

FastAPI 路径操作高级配置详解:自定义 OpenAPI operationId、从文档排除与 openapi_extra 深度定制

FastAPI 路径操作高级配置详解:自定义 OpenAPI operationId、从文档排除与 openapi_extra 深度定制 FastAPI 路径操作高级配置详解自定义 OpenAPI operationId、从文档排除与 openapi_extra 深度定制【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi本文基于 FastAPI 官方文档《Fortgeschrittene Konfiguration der Pfadoperation》路径操作高级配置整理聚焦于对单个路径操作path operation进行 OpenAPI 层面的精细控制通过operation_id自定义操作 ID、通过generate_unique_id_function改变 operationId 生成规则、用include_in_schemaFalse将接口从 OpenAPI 文档中剔除、利用 Docstring 中的换页符form feed截断描述、以及借助openapi_extra向 OpenAPI 操作对象注入扩展字段与自定义 requestBody 定义。读完本文你将掌握这套低层级扩展点的完整用法并能结合 fastapi/routing.py 的源码理解每个参数在路由创建时的实际处理逻辑。路径操作高级配置参数总览FastAPI 在装饰器如app.get、app.post上提供了一组只影响 OpenAPI 元数据、不影响运行时行为的高级参数。结合官方文档与 fastapi/routing.py 中的路由参数定义operation_id、include_in_schema、openapi_extra、generate_unique_id_function等字段在APIRoute构造参数中出现见 fastapi/routing.py各参数作用如下参数类型默认值作用operation_idstr \| NoneNone手动指定该路径操作的 OpenAPIoperationId必须全局唯一generate_unique_id_functionCallable[[APIRoute], str]FastAPI 内置默认函数在FastAPI()实例上配置用于替代默认的 operationId 生成策略include_in_schemaboolTrue设为False时将该路径操作从 OpenAPI Schema 及自动文档系统中排除openapi_extradict \| NoneNone以 Deep Merge 方式合并进自动生成的操作 OpenAPI 对象可添加扩展字段或补全requestBody等Docstring 中的\f换页符—截断用于 OpenAPI 的描述文本截断后的内容供 Sphinx 等其他工具使用这些参数共同作用于 OpenAPI 规范中的Operation Object操作对象它包含tags、parameters、requestBody、responses等全部路径操作信息是 FastAPI 自动文档Swagger UI的渲染数据源。理解这一点是理解后续所有高级配置的基础。自定义 OpenAPI operationId使用 operation_id 参数operationId是 OpenAPI 中每个操作的唯一标识客户端代码生成工具如 OpenAPI Generator通常依赖它生成函数名。如果你需要控制这个值可以通过operation_id参数直接指定from fastapi import FastAPI app FastAPI() app.get(/items/, operation_idsome_specific_id_you_define) async def read_items(): return [{item_id: Foo}]完整示例见 tutorial001_py310.py。注意官方文档在此处明确提示——如果你不是 OpenAPI 专家通常不需要这个功能。但一旦使用必须保证每个操作的operationId在整个 API 中唯一否则不符合 OpenAPI 规范。从源码看这一参数的优先级逻辑非常直接在APIRoute创建时执行route.unique_id route.operation_id or current_generate_unique_id(route)见 fastapi/routing.py即显式传入的operation_id优先生效否则回退到当前生效的generate_unique_id_function。使用函数名作为 operationId如果你希望直接用 API 函数的名字作为operationId比如read_items而不是默认生成的组合 ID可以给FastAPI实例传入一个自定义的generate_unique_id_functionfrom fastapi import FastAPI from fastapi.routing import APIRoute def custom_generate_unique_id(route: APIRoute) - str: return route.name app FastAPI(generate_unique_id_functioncustom_generate_unique_id) app.get(/items/) async def read_items(): return [{item_id: Foo}]完整示例见 tutorial002_py310.py。该回调接收每个APIRoute对象并返回该路径操作应使用的operationId。注意这样做后必须确保每个路径操作函数的名字唯一——即使它们位于不同的模块不同的 Python 文件中也不行因为最终生成的operationId不再包含模块路径信息。作为对照FastAPI 默认的 operationId 生成为「函数名 路径 方法」的组合。官方文档给出的/openapi.json输出示例中可以看到这一点函数read_items、路径/items/、方法get生成的 ID 是read_items_items__get。测试用例 test_generate_unique_id_function.py 验证了自定义generate_unique_id_function的注入行为。从 OpenAPI 中排除路径操作要把某个路径操作从生成的 OpenAPI Schema以及自动文档系统中完全剔除将include_in_schema参数设为Falsefrom fastapi import FastAPI app FastAPI() app.get(/items/, include_in_schemaFalse) async def read_items(): return [{item_id: Foo}]完整示例见 tutorial003_py310.py。该接口仍然可以正常响应请求只是不会出现在/docs、/redoc和/openapi.json中——适合内部接口、健康检查、调试端点等不希望暴露在公共文档里的路由。从源码结构看include_in_schema支持逐级传递在include_router场景下最终生效的值是「父级路由器的include_in_schemaand子路由的include_in_schema」见 fastapi/routing.py 与 fastapi/routing.py 中self.include_in_schema and include_in_schema的合并逻辑。这意味着只要应用级、Router级或路由级任意一层关闭了 schema 输出该路由就会从 OpenAPI 中消失这是一种「一票否决」的语义。用 Docstring 实现进阶描述Form Feed 截断你可以精确限制 Docstring 中哪些行会被用于 OpenAPI 描述在 Docstring 中插入一个\fform feed换页符字符FastAPI 就会把用于 OpenAPI 的描述截断到该符号之前。截断掉的部分不会显示在自动文档中但 Sphinx 等其他工具仍可读取完整 Docstring例如:param item:这样的文档参数说明。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/, summaryCreate 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 doesnt have tax, you can omit this - **tags**: a set of unique tag strings for this item \f :param item: User input. return item完整示例见 tutorial004_py310.py。上例中OpenAPI 描述只包含\f之前的「Create an item with all the information: ...」部分而\f之后的:param item: User input.仅对 Sphinx 类工具可见。这一行为在源码中有明确注释「if a form feed character (page break) is found in the description text, truncate description text to the content preceding the first form feed」见 fastapi/routing.py。对应的回归测试是 test_get_model_definitions_formfeed_escape.py 与 test_openapi_model_description_trim_on_formfeed_escape.py保证该转义字符在模型描述中同样被正确处理。额外 Responsesadditional responses你已经见过如何为路径操作声明response_model与status_code它们定义了路径操作主 Response即成功响应的元数据。除此之外你还可以声明额外的 Responses——例如 400 请求参数错误、500 服务器内部错误等状态码并为它们各自定义模型、示例、描述。官方文档为这一主题准备了独立章节可继续阅读 额外 Responses in OpenAPI其中涵盖了responses参数、Response对象、状态码复用与模型声明等完整用法。OpenAPI Extra低层级扩展点当你用 FastAPI 声明一个路径操作时框架会自动生成该操作相关的 OpenAPI 元数据即 OpenAPI 规范中的 Operation Object它包含tags、parameters、requestBody、responses等全部信息并用于构建自动文档。这个操作级 OpenAPI Schema 默认完全由 FastAPI 自动生成但你可以通过openapi_extra参数对其进行扩展。提示openapi_extra是一个低层级low-level扩展点。如果你只是需要声明额外 Responses用上一节提到的responses参数会更加便捷。声明 OpenAPI 扩展字段x- 前缀openapi_extra的典型用途之一是声明 OpenAPI 规范允许的Specification Extensions——即x-前缀的自定义字段许多 API 平台工具会读取这些字段from fastapi import FastAPI app FastAPI() app.get(/items/, openapi_extra{x-aperture-labs-portal: blue}) async def read_items(): return [{item_id: portal-gun}]完整示例见 tutorial005_py310.py。打开自动文档页面时该扩展会显示在对应路径操作信息区的末尾查看/openapi.json时扩展字段作为该路径操作对象的成员出现注意第 22 行的x-aperture-labs-portal{ openapi: 3.1.0, info: { title: FastAPI, version: 0.1.0 }, paths: { /items/: { get: { summary: Read Items, operationId: read_items_items__get, responses: { 200: { description: Successful Response, content: { application/json: { schema: {} } } } }, x-aperture-labs-portal: blue } } } }自定义 OpenAPI 路径操作 Schema手动声明 requestBodyopenapi_extra传入的字典会与自动生成的 OpenAPI 操作 Schema 进行深度合并Deep Merge因此你可以向自动生成的 Schema 中补充任意缺失的数据。一个典型场景你选择自己读取和校验请求体不使用 FastAPI 基于 Pydantic 的自动解析功能但仍希望在 OpenAPI 中定义请求体结构。这正是openapi_extra的用武之地from fastapi import FastAPI, Request app FastAPI() def magic_data_reader(raw_body: bytes): return { size: len(raw_body), content: { name: Maaaagic, price: 42, description: Just kiddin, no magic here. ✨, }, } app.post( /items/, openapi_extra{ requestBody: { content: { application/json: { schema: { required: [name, price], type: object, properties: { name: {type: string}, price: {type: number}, description: {type: string}, }, } } }, required: True, }, }, ) async def create_item(request: Request): raw_body await request.body() data magic_data_reader(raw_body) return data完整示例见 tutorial006_py310.py。在这个示例中没有声明任何 Pydantic 模型。请求体甚至不会被 FastAPI 当作 JSON 解析而是通过request.body()直接以bytes读入由magic_data_reader()自行决定如何解析。尽管如此我们仍然通过openapi_extra中的requestBody完整声明了期望的请求体 JSON Schema——自动文档与/openapi.json会如实展示该结构供客户端和文档读者参考。自定义 OpenAPI Content-Type非 JSON 请求体同样的技巧可以进一步推广借助 Pydantic 模型手动生成JSON Schema把它放进自定义的 OpenAPI 操作 Schema 中——即使请求体本身并不是 JSON。下面的应用既不使用 FastAPI 内置的「从 Pydantic 模型提取 JSON Schema」功能也不使用自动 JSON 校验。请求的 Content-Type 被声明为YAML而非 JSONimport yaml from fastapi import FastAPI, HTTPException, Request from pydantic import BaseModel, ValidationError app FastAPI() class Item(BaseModel): name: str tags: list[str] app.post( /items/, openapi_extra{ requestBody: { content: {application/x-yaml: {schema: Item.model_json_schema()}}, required: True, }, }, ) async def create_item(request: Request): raw_body await request.body() try: data yaml.safe_load(raw_body) except yaml.YAMLError: raise HTTPException(status_code422, detailInvalid YAML) try: item Item.model_validate(data) except ValidationError as e: raise HTTPException(status_code422, detaile.errors(include_urlFalse)) return item完整示例见 tutorial007_py310.py。该示例的工作流程分为三步定义模型并手动导出 Schema虽然不走内置的 Schema 提取通道仍使用Item.model_json_schema()生成 Pydantic 模型对应的 JSON Schema放进openapi_extra的requestBody.content[application/x-yaml]中——注意此处 Content-Type 是application/x-yaml直接读取原始请求体通过request.body()拿到bytesFastAPI 完全不会尝试把 Payload 解析为 JSON自行解析与校验用yaml.safe_load解析 YAML 内容失败时返回 422「Invalid YAML」再用同一个Item模型调用model_validate完成数据校验ValidationError同样映射为 422并返回include_urlFalse的简洁错误详情。提示此处复用了同一个 Pydantic 模型做校验但同样可以换成任何其他校验方式——openapi_extra只负责描述「文档里长什么样」运行时的校验逻辑完全由你自己的代码掌控。小结何时使用路径操作高级配置需求推荐手段需要固定/规范化的 operationId客户端代码生成operation_id参数全局改用函数名等策略生成 operationIdFastAPI(generate_unique_id_function...)内部接口不进入自动文档include_in_schemaFalse支持 Router 级「一票否决」Docstring 过长只想让部分文字进 OpenAPIDocstring 中插入\f换页符声明额外错误状态码及模型responses参数见 额外 Responses in OpenAPI注入x-扩展字段openapi_extra绕过自动解析、手动读取/校验请求体但仍需文档化请求结构openapi_extraRequest.body()非 JSON Content-Type如 YAML但希望文档中体现 Schemaopenapi_extra 手动model_json_schema()这些高级配置的共同特点是只改变 OpenAPI 元数据的生成结果不改变 FastAPI 的请求路由与响应机制本身。理解operation_id or generate_unique_id_function的优先级fastapi/routing.py、include_in_schema的逐级 AND 合并fastapi/routing.py、form feed 截断fastapi/routing.py以及openapi_extra的 Deep Merge 语义就能在「文档即契约」的 API 设计中对 OpenAPI 输出做到像素级的精确控制。【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表