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

资讯详情

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

FastAPI 请求体之嵌套模型(Nested Models):用 Pydantic 构建任意深度的数据模型与校验

FastAPI 请求体之嵌套模型(Nested Models):用 Pydantic 构建任意深度的数据模型与校验 FastAPI 请求体之嵌套模型Nested Models用 Pydantic 构建任意深度的数据模型与校验【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi本篇指南围绕 FastAPI 教程的“Body - Nested Models”展开讲解如何基于 Pydantic 在请求体中声明list、set、dict以及层层嵌套的模型从而获得类型提示、数据转换、校验与自动文档。读完你将掌握从简单的tags: list[str]到模型套模型、模型套列表、纯数组请求体、dict[int, float]任意字典体的完整写法并了解仓库源码示例与测试对每一种行为的验证方式。概述为什么需要嵌套模型在编写 API 时请求体往往不是一层简单的键值对而是结构化的 JSON 对象。FastAPI基于Pydantic允许你定义、校验、文档化并使用任意深度嵌套的模型——这正是本教程韩文原文档内容与 英文文档 一致的核心主张。你只要在路径操作函数中把参数类型声明为一个 Pydantic 模型FastAPI 便会自动完成四项工作编辑器支持自动补全等嵌套模型同样生效数据转换解析 / 序列化即 parsing / serialization数据校验非法请求返回带详细错误信息的 422 响应自动文档JSON Schema 与 OpenAPI进而在 Swagger UI 中呈现。下文所有的代码示例均来自仓库 docs_src/body_nested_models/并且每个示例都有对应的自动化测试见 tests/test_tutorial/test_body_nested_models/作为行为佐证。列表字段先声明它是一个 list最基础的场景是模型的一个属性是列表。定义一个属性为 Pythonlist类型即可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: list [] app.put(/items/{item_id}) async def update_item(item_id: int, item: Item): results {item_id: item_id, item: item} return results完整代码见 tutorial001_py310.py。需要注意tags: list只声明了tags 是一个列表并没有声明列表中元素的类型。元素类型留空意味着它可以容纳任意类型的值校验粒度较粗。若要精细化就需要用到带类型参数的列表。带类型参数的列表字段list[str]Python 中声明内部有类型的容器类型list、dict、tuple等有专门语法用方括号[、]把内部类型作为类型参数传入例如my_list: list[str]这是标准的 Python 类型声明语法Pydantic 模型的属性同样遵循。把上面例子的tags精确声明为字符串组成的列表class Item(BaseModel): name: str description: str | None None price: float tax: float | None None tags: list[str] []见 tutorial002_py310.py第 12 行为tags: list[str] []。一旦声明了元素类型FastAPI/Pydantic 就会对列表中的每一个元素分别做类型转换与校验并在文档中标注tags是string的数组。集合类型用set[str]去重回到业务思考标签tags通常不应重复应当是唯一的字符串。Python 恰好有专门表达唯一元素集合的类型set。于是把tags声明为字符串集合class Item(BaseModel): name: str description: str | None None price: float tax: float | None None tags: set[str] set()见 tutorial003_py310.py。使用set带来三个直接效果文档原文明确列出入站去重即使收到带重复数据的请求也会被转换成唯一元素的集合出站去重每次输出该数据时即使源头存在重复也按唯一元素集合输出按语义标注文档JSON Schema / OpenAPI 会相应地把该字段标记为uniqueItems: true的数组。也就是说客户端若发送tags: [rock, rock, metal]服务端最终接收/返回的将是{rock, metal}这类唯一集合。对应验证测试见 test_tutorial001_tutorial002_tutorial003.py。嵌套模型模型里面再放一个模型Pydantic 模型的每个属性都有自己的类型而这个类型本身可以又是一个 Pydantic 模型。于是你可以用指定的属性名、类型与校验规则声明出层层嵌套的 JSON对象而且嵌套深度任意。定义子模型先定义一个小模型Imagefrom fastapi import FastAPI from pydantic import BaseModel app FastAPI() class Image(BaseModel): url: str name: str把子模型当作属性类型再在Item里把image声明为Image | None可选允许缺省class Item(BaseModel): name: str description: str | None None price: float tax: float | None None tags: set[str] set() image: Image | None None app.put(/items/{item_id}) async def update_item(item_id: int, item: Item): results {item_id: item_id, item: item} return results完整代码见 tutorial004_py310.py子模型定义在第 7–9 行嵌套使用在第 18 行。这样一来FastAPI 期望的请求体大致形如{ name: Foo, description: The pretender, price: 42.0, tax: 3.2, tags: [rock, metal, bar], image: { url: http://example.com/baz.jpg, name: The Foo live } }image字段不再是一个普通字符串而是一个完整的、由Image模型约束的对象url与name均必填且会被校验。仅凭一次类型声明FastAPI 就同时给出编辑器自动补全、数据转换、数据校验与自动文档化。测试见 test_tutorial004.py。特殊类型与校验HttpUrl代替str除了str、int、float这类普通单值类型你还可以使用从str派生的更复杂单值类型从而在不写一行自定义校验逻辑的情况下获得额外约束。例如Image.url本是str可以改声明为 Pydantic 的HttpUrl类型from fastapi import FastAPI from pydantic import BaseModel, HttpUrl app FastAPI() class Image(BaseModel): url: HttpUrl name: str见 tutorial005_py310.py第 2 行导入HttpUrl第 8 行使用。行为变化该字符串会被校验是否为合法的 URL在 JSON Schema / OpenAPI 中会按 URL 格式format: uri正确文档化Swagger UI 中呈现为专门的 URL 输入框。FastAPI 文档指出Pydantic 的类型全貌可参考其官方 Type Overview后续教程章节还会给出更多示例。本仓库的校验行为可参考 test_tutorial005.py其中包含了合法 URL 与非法 URL 两类断言。子模型组成的列表list[Image]Pydantic 模型同样可以作为list、set等容器的元素子类型。把单个image扩展为多个图像class Image(BaseModel): url: HttpUrl name: str class Item(BaseModel): name: str description: str | None None price: float tax: float | None None tags: set[str] set() images: list[Image] | None None见 tutorial006_py310.py第 18 行。此时 FastAPI 期望并会转换、校验、文档化类似下面的 JSON{ name: Foo, description: The pretender, price: 42.0, tax: 3.2, tags: [ rock, metal, bar ], images: [ { url: http://example.com/baz.jpg, name: The Foo live }, { url: http://example.com/dave.jpg, name: The Baz } ] }注意其中的关键变化images键现在携带的是一个图片对象数组数组里的每个元素都独立受Image模型约束。测试见 test_tutorial006.py。深度嵌套模型模型任意套模型上述技巧可以自由组合构成任意深度的嵌套结构。教程给出了三层嵌套的典型例子——Offer拥有若干Item而每个Item又拥有可选的Image列表class Image(BaseModel): url: HttpUrl name: str class Item(BaseModel): name: str description: str | None None price: float tax: float | None None tags: set[str] set() images: list[Image] | None None class Offer(BaseModel): name: str description: str | None None price: float items: list[Item] app.post(/offers/) async def create_offer(offer: Offer): return offer见 tutorial007_py310.py模型行号为 7、12、18、21、25路径操作在第 28–30 行。这里三层结构清晰可读Offer→name/description/price/itemsitems→ 一个Item列表每个Item→images又是一个可选的Image列表。声明完全由标准 Python 类型注解驱动没有额外的配置代码校验、文档化同样层层生效。测试见 test_tutorial007.py。纯列表的请求体list[Image]作顶层参数有时期望的 JSON 请求体最顶层就是一个数组Pythonlist而不包在一个对象里。此时可以像在 Pydantic 模型内部那样直接在路径操作函数的参数上声明类型images: list[Image]示例代码from fastapi import FastAPI from pydantic import BaseModel, HttpUrl app FastAPI() class Image(BaseModel): url: HttpUrl name: str app.post(/images/multiple/) async def create_multiple_images(images: list[Image]): return images见 tutorial008_py310.py第 13 行。请求体形如[{...Image...}, {...Image...}]数组中每个元素都按Image校验函数参数会收到一个Image实例组成的列表。测试见 test_tutorial008.py。无处不在的编辑器支持由于一切均基于类型注解而非手写dict解析你可以在任何地方获得编辑器补全——连列表内部元素的字段也会被识别文档特别对比了两种做法如果直接用dict手工处理请求体就无法获得这种编辑器支持字段名一旦拼错只能等到运行时才发现但你也不必担心类型声明与运行数据之间的鸿沟进入的dict会被自动转换为 Pydantic 模型实例输出时也会自动序列化回 JSON——两边都是自动的。任意dict请求体dict[int, float]最后一个场景把请求体声明为键为某类型、值为另一类型的字典。与使用 Pydantic 模型不同这种方式不需要预先知道合法的字段/属性名有哪些——对希望接收尚不可预知键名的接口特别有用例如用户自定义元数据。另一个实用场景是想要非字符串键。下面的例子接收任意字典只要它的键是int、值是floatfrom fastapi import FastAPI app FastAPI() app.post(/index-weights/) async def create_index_weights(weights: dict[int, float]): return weights见 tutorial009_py310.py第 7 行为类型声明。这里有一个 JSON 与 Python 的重要差异需要牢记教程中的 tip 明确强调JSON 只支持str作为对象的键。也就是说你的 API 客户端只能发送字符串键。但因为 Pydantic 具备自动数据转换能力只要发送的字符串包含纯整数如2Pydantic 就会把它转换并校验为int键最终你在weights参数中拿到的确实是一个int键、float值的字典。这一行为在仓库测试中有精确印证——test_tutorial009.py 中发送{2: 2.2, 3: 3.3}返回 200响应体与原数据一致发送{foo: 2.2, 3: 3.3}键foo不是纯整数则返回422 校验错误错误项为int_parsing错误路径定位到[body, foo, [key]]信息为 unable to parse string as an integer同时该测试用快照断言了/index-weights/的 OpenAPI schema请求体类型为objectadditionalProperties为{type: number}印证任意键字典在 OpenAPI 文档中以additionalProperties呈现。小结借助FastAPI与 Pydantic你可以获得模型体系的最大灵活性同时保持代码简单、简短、优雅并附带完整的工程收益编辑器支持处处自动补全数据转换即解析 / 序列化数据校验Schema 文档化JSON Schema / OpenAPI自动交互文档Swagger UI。从单层对象到集合去重再到三层嵌套与纯数组/任意字典请求体核心始终是标准 Python 类型注解——FastAPI 负责把注解翻译成校验、转换与文档。所有示例源码集中在 docs_src/body_nested_models/对应行为测试位于 tests/test_tutorial/test_body_nested_models/可作为继续实验与回归验证的参考。【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表