ARTICLE DETAIL

资讯详情

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

FastAPI 额外数据类型详解:UUID、日期时间、timedelta 与更多高级类型

FastAPI 额外数据类型详解:UUID、日期时间、timedelta 与更多高级类型 FastAPI 额外数据类型详解UUID、日期时间、timedelta 与更多高级类型【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi导读本篇指南以 FastAPI 官方教程中的 额外数据类型Extra Data Types 一节为骨架系统讲解如何在路径参数、查询参数与请求体中使用UUID、datetime、date、time、timedelta、frozenset、bytes、Decimal等更复杂的数据类型。读完本文你将掌握这些类型在请求解析、响应序列化、校验与 OpenAPI 文档生成中的完整行为并能直接在自己的 API 项目中正确选用它们。为什么需要额外数据类型在此之前教程中演示的多是int、float、str、bool这类基础类型。但真实业务中接口经常需要表达商品的唯一 ID、订单的创建时间、一次任务的耗时、文件的二进制内容等语义更强的数据。如果全部退化成字符串或数字就会丢失类型信息校验、序列化和文档都会变得含糊。使用 FastAPI 声明这些额外类型后你依然能获得与基础类型完全一致的开发体验出色的编辑器支持类型提示、自动补全、静态检查来自请求数据的自动类型转换例如将请求体中的 ISO 8601 字符串转换为datetime对象响应数据的自动转换例如把timedelta序列化为总秒数自动数据校验格式非法时返回 422 校验错误自动注解与文档生成OpenAPI 中自动填充format等元信息。这些能力并非 FastAPI 自行实现而是基于 Pydantic 的字段类型系统FastAPI 在此基础上完成了请求/响应两侧的 JSON 编解码与 OpenAPI 模式生成。额外数据类型清单UUID含义标准通用唯一标识符广泛用作数据库与各类系统中的 ID。请求/响应表示在 JSON 中以str形式出现。声明方式直接用作路径参数或字段类型例如item_id: UUID。底层行为FastAPI 会将其校验为合法的 UUID v1~v5 格式非法字符串将触发 422 校验错误生成的 OpenAPI 模式中表现为type: string, format: uuid。datetime.datetime含义Python 标准库中的datetime.datetime。请求/响应表示ISO 8601 格式字符串例如2008-09-15T15:53:0005:00。附加价值一旦被解析为真实的datetime对象你就可以在视图函数内直接进行日期运算见下文示例。OpenAPI 模式type: string, format: date-time。datetime.date含义Python 标准库中的datetime.date。请求/响应表示ISO 8601 日期格式字符串例如2008-09-15无时间部分。OpenAPI 模式type: string, format: date。datetime.time含义Python 标准库中的datetime.time。请求/响应表示ISO 8601 时间格式字符串例如14:23:55.003。OpenAPI 模式type: string, format: time。datetime.timedelta含义Python 标准库中的datetime.timedelta表示一段时间差。请求/响应表示以总秒数的float出现。例如测试用例中的300秒即表示 5 分钟见 tests/test_tutorial/test_extra_data_types/test_tutorial001.py。序列化依据FastAPI 在 fastapi/encoders.py 中通过lambda td: td.total_seconds()将timedelta编码为总秒数。扩展说明Pydantic 还允许将其表示为ISO 8601 时间差编码OpenAPI 模式中对应format: duration如需自定义序列化方式可参考 Pydantic 自定义序列化器的相关文档。frozenset含义不可变的 Python 集合。请求侧JSON 数组会被读取为列表自动去重后转换为frozenset。响应侧序列化回 JSON 数组frozenset在 fastapi/encoders.py 中被映射为list。OpenAPI 模式生成的 JSON Schema 会通过uniqueItems明确标注集合内元素唯一。bytes含义Python 标准bytes。请求/响应表示按str处理。序列化依据在 fastapi/encoders.py 中通过lambda o: o.decode()解码为字符串。OpenAPI 模式声明为type: string且带binary格式。Decimal含义Python 标准Decimal高精度十进制数。请求/响应表示与float相同的方式处理。序列化依据在 fastapi/encoders.py 中的decimal_encoder会智能处理若无指数部分如Decimal(1)编码为int否则如Decimal(1.0)、Decimal(NaN)编码为float从而保证Numeric(x,0)这类场景能够正确往返。完整类型清单可进一步查阅 Pydantic 官方数据类型的文档Pydantic Data Types。完整示例在路径操作中使用额外类型以下是官方教程使用的示例对应源码 docs_src/extra_data_types/tutorial001_an_py310.py该示例定义了一个PUT操作路径参数使用UUID请求体通过Body()声明datetime、timedelta与可选的timefrom datetime import datetime, time, timedelta from typing import Annotated from uuid import UUID from fastapi import Body, FastAPI app FastAPI() app.put(/items/{item_id}) async def read_items( item_id: UUID, start_datetime: Annotated[datetime, Body()], end_datetime: Annotated[datetime, Body()], process_after: Annotated[timedelta, Body()], repeat_at: Annotated[time | None, Body()] None, ): start_process start_datetime process_after duration end_datetime - start_process return { item_id: item_id, start_datetime: start_datetime, end_datetime: end_datetime, process_after: process_after, repeat_at: repeat_at, start_process: start_process, duration: duration, }对于不使用Annotated语法的版本Python 3.10 以上同样可用仓库同时提供了 tutorial001_py310.py两者行为完全一致仅声明风格不同app.put(/items/{item_id}) async def read_items( item_id: UUID, start_datetime: datetime Body(), end_datetime: datetime Body(), process_after: timedelta Body(), repeat_at: time | None Body(defaultNone), ): ...注意其中几个要点请求体中的额外类型参数都用Body()显式标记repeat_at是可选的默认None因此它在 OpenAPI 的required列表中不会出现参数在函数内部保持其自然 Python 类型所以可以直接做日期运算例如start_process start_datetime process_after得到处理开始时间duration end_datetime - start_process得到处理耗时。请求与响应行为验证测试用例拆解仓库中针对该教程编写了自动化测试 tests/test_tutorial/test_extra_data_types/test_tutorial001.py同时参数化覆盖tutorial001_py310与tutorial001_an_py310两个源码变体可直接用于验证上述行为请求数据JSON{ start_datetime: 2018-12-22T14:00:0000:00, end_datetime: 2018-12-24T15:00:0000:00, repeat_at: 15:30:00, process_after: 300 }预期响应测试断言item_id原样回传start_process为2018-12-22T14:05:0000:00即开始时间加 300 秒duration为176100秒即两天多一点的耗时差。这直观印证了ISO 8601 字符串 →datetime→ 参与运算 → 再序列化为 ISO 8601 字符串timedelta300 秒→ 加法运算 → 结果序列化为总秒数float。OpenAPI 快照断言测试还校验了/openapi.json的输出其中路径参数item_id的模式为type: string, format: uuidstart_datetime、end_datetime为type: string, format: date-timerepeat_at为anyOf: [{type: string, format: time}, {type: null}]体现可选性process_after为type: string, format: durationrequired列表仅包含start_datetime、end_datetime、process_after。这说明 OpenAPI 文档生成是完全自动的无需手写任何模式注解。底层原理FastAPI 如何完成序列化所有额外类型在响应侧的序列化最终汇聚到 fastapi/encoders.py 中的ENCODERS_BY_TYPE字典fastapi/encoders.py它按类型注册了转换函数类型编码函数结果byteslambda o: o.decode()strdatetime.date/datetime.datetime/datetime.timeisoformat即o.isoformat()ISO 8601strdatetime.timedeltalambda td: td.total_seconds()float总秒数Decimaldecimal_encoder无指数时int否则floatfrozenset/setlistJSON 数组UUIDstr字符串形式的 UUID从源码结构可以推断请求侧的解析与校验由 Pydantic 的字段类型系统完成FastAPI 将路径、查询、请求体等来源的参数收集后交给 Pydantic 建模校验响应侧再借助ENCODERS_BY_TYPE将 Python 对象规范化为 JSON 可序列化值。这两条链路共同保证了声明即获得校验、序列化与文档的开发体验。使用建议与注意事项优先用强类型表达语义ID 用UUID、时间点用datetime、只关心日期用date、一天内的时刻用time、时间差用timedelta让 OpenAPI 文档与编辑器提示都能准确反映业务含义。timedelta的单位是秒客户端需要按总秒数可以是小数提交或解析例如300表示 5 分钟176100表示约 2 天 0 小时 55 分钟。datetime依赖python-multipart之外的纯标准库datetime、uuid均来自 Python 标准库无需额外安装依赖Decimal同理。校验失败返回 422当请求中的UUID格式非法、datetime字符串不符合 ISO 8601 时FastAPI 会返回包含ValidationError详情的 422 响应测试快照中可以看到该错误模式的完整结构。Annotated与默认值语法二选一即可新版推荐使用Annotated[type, Body()]风格旧式type Body(default...)依然可用且测试覆盖二者生成的请求体与文档完全一致。更多类型Pydantic 生态还提供 IP 地址、URL、枚举、秘密字符串等类型FastAPI 的ENCODERS_BY_TYPE中同样注册了对应编码如IPv4Address: str、SecretStr: str、Enum: lambda o: o.value等可按需查阅 fastapi/encoders.py 与 Pydantic 类型文档进一步扩展。小结额外数据类型让 FastAPI 接口从只有基础类型升级为任意丰富的领域类型且全程保持自动转换、自动校验与自动文档。通过本文的示例与测试证据可以看到声明UUID、日期时间族、timedelta、frozenset、bytes、Decimal后请求解析、函数内运算、响应序列化与 OpenAPI 模式生成全部开箱即用无需手写任何样板代码。【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表