十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

FastAPI 路径参数(Path Parameters)完整实战指南:声明语法、类型转换与校验、Enum 限定值及 path 转换器

FastAPI 路径参数(Path Parameters)完整实战指南:声明语法、类型转换与校验、Enum 限定值及 path 转换器 FastAPI 路径参数Path Parameters完整实战指南声明语法、类型转换与校验、Enum 限定值及 path 转换器【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi路径参数是 RESTful API 设计中最基础也最常用的部分它把可变内容直接放进 URL 路径例如/items/42中的42。本指南以 FastAPI 官方 Tutorial 的《Path Parameters》章节为主线对应本仓库 docs/hi/docs/tutorial/path-params.md其英文原文位于 docs/en/docs/tutorial/path-params.md带你掌握如何用与 Python format string 相同的语法声明路径参数、如何借助标准 Python 类型注解获得数据解析与校验、如何利用Enum限定合法取值以及如何让路径参数本身承载一段完整路径。读完你将能独立写出带类型安全路径参数、可自动生成交互式文档的 FastAPI 接口。用 format string 语法声明路径参数FastAPI 允许你在app.get(...)这类装饰器中用与 Python 字符串格式化相同的花括号语法把 URL 中的某一段声明为参数或变量。第一个示例来自 docs_src/path_params/tutorial001_py310.pyfrom fastapi import FastAPI app FastAPI() app.get(/items/{item_id}) async def read_item(item_id): return {item_id: item_id}路径中的{item_id}是一个路径参数占位符当请求打到/items/foo时foo这一小段会被提取出来作为名为item_id的参数传入你的函数read_item(item_id)因此返回体就是{item_id:foo}要点是函数参数名必须与 URL 路径中花括号内的名字保持一致——FastAPI 靠名字把 URL 片段绑定到函数参数上。如何运行验证把上述代码保存为main.py仓库文档源码中每个教程文件都对应独立可运行的应用再用任意 ASGI 服务器启动即可例如uvicorn main:app --reload。随后在浏览器访问http://127.0.0.1:8000/items/foo即可看到上面的 JSON 响应。用标准类型注解声明路径参数类型路径参数不必永远是字符串。你可以在函数签名上为它标注 Python 标准类型见 docs_src/path_params/tutorial002_py310.pyfrom fastapi import FastAPI app FastAPI() app.get(/items/{item_id}) async def read_item(item_id: int): return {item_id: item_id}这里把item_id声明为int。类型注解会带来三重连锁收益编辑器支持函数体内可得到类型推断、错误检查与自动补全数据解析请求 URL 中的字符串会被转换为 Python 数据类型数据校验无法转换的值会被拒绝并返回结构化错误。数据转换Parsing字符串 → int当你访问http://127.0.0.1:8000/items/3时返回的是{item_id:3}注意响应里是3不带引号——函数收到并返回的是 Python 的int而不是字符串3。也就是说仅凭item_id: int这一处声明FastAPI 就自动完成了把 HTTP 请求字符串解析成 Python 数据的动作。数据校验非法输入返回结构化 422 错误如果访问http://127.0.0.1:8000/items/foo因为foo无法解析成int你会收到一个格式规范的 HTTP 校验错误状态码 422{ detail: [ { type: int_parsing, loc: [ path, item_id ], msg: Input should be a valid integer, unable to parse string as an integer, input: foo } ] }同理如果把4.2浮点数当作int传入如访问http://127.0.0.1:8000/items/4.2也会出现完全相同的错误——int声明不接受浮点字面量。这个错误对象的结构很有价值字段含义type错误类别如int_parsing整型解析失败、后续会遇到的enum枚举值不在允许范围内等loc出错位置的定位链这里是[path, item_id]精确指明错误发生在路径参数item_id上msg面向开发者的可读错误说明input实际传入的原始值便于排查因为错误精确指出了是哪一处、哪一个参数、什么样的输入校验未通过你在开发、调试与 API 对接的代码时会非常省力。这条校验逻辑并非 FastAPI 单独实现而是由 Pydantic 完成的详见后文底层校验引擎一节其 v2 错误格式即为此结构。仓库中大量测试例如 tests/test_tutorial/test_path_params/test_tutorial005.py断言了 422 响应与错误 JSON 结构可作为验证依据。一份类型声明自动获得 Swagger UI 交互文档打开http://127.0.0.1:8000/docsFastAPI 会基于你写下的路径与类型声明自动生成交互式 API 文档集成 Swagger UI注意上图中item_id被正确渲染为integer类型、required: true——这些信息完全来自函数签名里的item_id: int你无需额外写任何配置。基于 OpenAPI 标准的替代文档ReDocFastAPI 生成的接口 schema 遵循 OpenAPI 标准因此天然兼容大量生态工具。官方自带的替代文档基于 ReDoc位于http://127.0.0.1:8000/redoc同样由于 schema 遵循 OpenAPI 标准社区存在大量可兼容工具包括面向多种语言的客户端代码生成工具。FastAPI 自身还暴露/openapi.json导出的正是这份标准化 schema。底层校验引擎Pydantic所有数据校验在内核层面都由 Pydantic 执行因此你直接享受 Pydantic 的全部能力与可靠性。类型声明的玩法不止int你还可以用str、float、bool以及许多更复杂的数据类型其中相当一部分会在教程后续章节如 Query 参数与请求体章节继续展开。仓库中 fastapi/_compat/ 与 fastapi/dependencies/utils.py 等模块承载了参数字段的构建与解析管线校验细节交由 Pydantic 完成。路径匹配顺序固定路径必须先于参数路径声明当路径操作path operation越来越多你会遇到固定路径 vs 参数路径重叠的场景。例如想用/users/me获取当前用户信息又用/users/{user_id}按 ID 获取某个用户的数据from fastapi import FastAPI app FastAPI() app.get(/users/me) async def read_user_me(): return {user_id: the current user} app.get(/users/{user_id}) async def read_user(user_id: str): return {user_id: user_id}关键原则/users/me必须在/users/{user_id}之前声明见 docs_src/path_params/tutorial003_py310.py。因为路径操作按声明顺序逐一匹配若反了顺序/users/me会先被/users/{user_id}匹配到——FastAPI 会以为收到的是值为me的参数user_id从而返回错误的结果。同理你不能重复定义同一个路径操作。即使注册了两个路径完全相同的接口见 docs_src/path_params/tutorial003b_py310.pyfrom fastapi import FastAPI app FastAPI() app.get(/users) async def read_users(): return [Rick, Morty] app.get(/users) async def read_users2(): return [Bean, Elfo]由于匹配总是取先命中的路由永远只会执行第一个/users返回[Rick, Morty]第二个定义实际上不可达。这与 FastAPI 路由表的顺序匹配机制一致——在 fastapi/routing.py 中每条路由都会把路径编译为正则表达式并按注册顺序参与匹配。对应测试见 tests/test_tutorial/test_path_params/test_tutorial003.py 与 tests/test_tutorial/test_path_params/test_tutorial003b.py。用 Python Enum 限定路径参数的预定义取值当路径参数的合法取值应当被限定为一组固定的值例如枚举机器学习模型名时标准 Python 的Enum就是最自然的工具。创建str与Enum的子类首先导入Enum并创建一个同时继承str与Enum的子类from enum import Enum from fastapi import FastAPI class ModelName(str, Enum): alexnet alexnet resnet resnet lenet lenet app FastAPI()这里的继承有两个讲究继承str后API 文档能识别这些值属于string类型并正确渲染每个类属性alexnet alexnet等的取值就是该参数可用的合法值。顺带一提AlexNet、ResNet、LeNet只是机器学习深度学习模型架构的名字用于示例而已。声明一个枚举类型的路径参数用上面创建的ModelName作为类型注解来声明路径参数app.get(/models/{model_name}) async def get_model(model_name: ModelName): if model_name is ModelName.alexnet: return {model_name: model_name, message: Deep Learning FTW!} if model_name.value lenet: return {model_name: model_name, message: LeCNN all the images} return {model_name: model_name, message: Have some residuals}完整代码见 docs_src/path_params/tutorial005_py310.py。因为合法取值已预定义交互式文档会把可选项清晰地呈现出来与枚举成员协同工作传入路径参数后函数收到的model_name是一个**枚举成员enumeration member**而非普通字符串你可以与枚举成员比较用model_name is ModelName.alexnetis或均可判断命中的是哪个分支获取枚举的原始值用model_name.value拿到真正的字符串值例如访问/models/lenet时model_name.value lenet。也随时可用ModelName.lenet.value直接取得常量lenet返回枚举成员可以直接把枚举成员放进返回值甚至嵌套在dict里FastAPI 会在返回客户端前把它们自动转换序列化成对应取值。因此访问/models/alexnet时客户端收到{ model_name: alexnet, message: Deep Learning FTW! }枚举越界的表现如果访问/models/foo不在合法集合内FastAPI 同样返回 422错误对象为{ detail: [ { type: enum, loc: [path, model_name], msg: Input should be alexnet, resnet or lenet, input: foo, ctx: {expected: alexnet, resnet or lenet} } ] }以上行为由仓库测试 tests/test_tutorial/test_path_params/test_tutorial005.py 完整覆盖/models/alexnet、/models/lenet、/models/resnet均返回 200 及各自分支文案而/models/foo返回 422。同时该测试还对/openapi.json做了快照断言——OpenAPI schema 中ModelName被建模为{type: string, enum: [alexnet, resnet, lenet]}这也解释了为何 Swagger UI 能以下拉候选的方式渲染这些取值。让路径参数包含路径本身path转换器某些场景下路径参数的取值本身又包含斜杠分隔的路径。例如定义/files/{file_path}却希望file_path能接住home/johndoe/myfile.txt即完整 URL 形如/files/home/johndoe/myfile.txt。OpenAPI 的限制OpenAPI 规范并不支持声明参数内部再含一段路径——因为这会引入难以测试与定义的匹配场景。即便如此FastAPI 仍然可以借助 Starlette 提供的内部工具实现该能力而且/docs交互文档依旧正常工作只是不会额外注明该参数需包含路径。使用 path 转换器语法是在参数名后追加:path/files/{file_path:path}其中file_path是参数名末尾的:path告诉路由该参数应贪婪匹配任意包含/的路径。示例见 docs_src/path_params/tutorial004_py310.pyfrom fastapi import FastAPI app FastAPI() app.get(/files/{file_path:path}) async def read_file(file_path: str): return {file_path: file_path}访问/files/home/johndoe/myfile.txt时file_path收到的值是home/johndoe/myfile.txt。如果参数需要保留开头的斜杠例如绝对路径/home/johndoe/myfile.txtURL 中会出现双斜杠/files//home/johndoe/myfile.txt——files与home之间是两个连续的/。这两条路径的行为在仓库测试 tests/test_tutorial/test_path_params/test_tutorial004.py 中被明确断言前者得到file_path: home/johndoe/myfile.txt后者得到file_path: /home/johndoe/myfile.txt。从实现上看这种带转换器convertor的路由会连同参数编译逻辑一起被处理在 fastapi/routing.py 中路由通过compile_path(path)一次性得到path_regex、path_format与param_convertors三件套{file_path:path}里的:path正是被这类转换器识别并赋予可含斜杠语义匹配请求时再经 fastapi/routing.py 的param_convertors[key].convert(value)把 URL 片段转为参数值。小结在 FastAPI 中仅凭短小、直观的标准 Python 类型声明一次声明就能同时得到编辑器支持类型错误检查、自动补全等数据解析把 HTTP 请求中的字符串转换为 Python 数据数据校验不合法的输入得到带精确定位的结构化 422 错误接口标注与自动文档Swagger UI、ReDoc 与/openapi.json自动生成兼容 OpenAPI 生态。声明路径参数时只需记住三条经验法则函数参数名与 URL 花括号中的名字必须一致类型用标准 Python 注解即可固定路径如/users/me务必声明在带参数的路径如/users/{user_id}之前且不要重复定义相同路径想让参数承接任意嵌套路径用{file_path:path}语法并留意双斜杠带来的前导斜杠处理。本指南对应的全部可运行示例位于 docs_src/path_params/官方测试位于 tests/test_tutorial/test_path_params/你可以直接在仓库中对照运行、验证作为学习路径参数的首选参考资料。【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表