ARTICLE DETAIL

资讯详情

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

使用 Litestar 组装完整 TODO 应用:路由处理器、参数注入与 ASGI 启动实战

使用 Litestar 组装完整 TODO 应用:路由处理器、参数注入与 ASGI 启动实战 使用 Litestar 组装完整 TODO 应用路由处理器、参数注入与 ASGI 启动实战【免费下载链接】litestarLight, flexible and extensible ASGI framework | Built to scale项目地址: https://gitcode.com/GitHub_Trending/li/litestar本篇技术指南基于 Litestar 官方 TODO 应用教程的收尾章节讲解如何把此前分别实现的列表查询、新增条目、更新条目三个路由处理器整合进同一个Litestar应用实例形成可运行的完整 ASGI 应用。读完本文你将掌握get/post/put装饰器的组合使用、FromQuery与FromPath参数注入的底层语义、data请求体注入规则以及通过litestar run一键启动应用的完整流程。从零散组件到完整应用装配阶段要做什么在此前教程的各个阶段我们分别独立实现过 TODO 应用的多个部件返回列表的GET处理器、接收数据的POST处理器、以及使用路径参数定位条目的PUT处理器。它们各自在自己的app.py里单独运行互不关联。本章的任务只有一个把它们放进同一个文件、注册到同一个Litestar实例中组装成一个功能完整的应用。完整可运行的最终应用源码位于 docs/examples/todo_app/full_app.py也是本教程app.py的最终形态from dataclasses import dataclass from litestar import Litestar, get, post, put from litestar.exceptions import NotFoundException from litestar.params import FromPath, FromQuery dataclass class TodoItem: title: str done: bool TODO_LIST: list[TodoItem] [ TodoItem(titleStart writing TODO list, doneTrue), TodoItem(title???, doneFalse), TodoItem(titleProfit, doneFalse), ] def get_todo_by_title(todo_name: str) - TodoItem: for item in TODO_LIST: if item.title todo_name: return item raise NotFoundException(detailfTODO {todo_name!r} not found) get(/) async def get_list(done: FromQuery[bool | None] None) - list[TodoItem]: if done is None: return TODO_LIST return [item for item in TODO_LIST if item.done done] post(/) async def add_item(data: TodoItem) - list[TodoItem]: TODO_LIST.append(data) return TODO_LIST put(/{item_title:str}) async def update_item(item_title: FromPath[str], data: TodoItem) - list[TodoItem]: todo_item get_todo_by_title(item_title) todo_item.title data.title todo_item.done data.done return TODO_LIST app Litestar([get_list, add_item, update_item])这份 49 行的文件看似简单实则浓缩了 Litestar 路由、参数注入、数据校验、异常处理和序列化等核心机制。下面按函数逐个拆解。GET /基于FromQuery的查询参数过滤第一个路由处理器负责读取 TODO 列表get(/) async def get_list(done: FromQuery[bool | None] None) - list[TodoItem]: if done is None: return TODO_LIST return [item for item in TODO_LIST if item.done done]用get(/)注册后该函数只响应GET请求路径为根路径/并返回当前 TODO 列表的全部条目。三个核心设计点FromQuery标记参数声明为done: FromQuery[bool | None]其中FromQuery是告诉 Litestar“这个值来自 URL 查询字符串”的标记。在源码层面它并不是一个普通类而是类型别名FromQuery: TypeAlias Annotated[T, QueryParameter()]见 litestar/params.py。Annotated的元数据被 Litestar 在签名解析阶段识别从而把该参数归类为查询参数并注入。内层类型触发转换bool不是原样透传Litestar 会先把 URL 中的字符串值转换为布尔值。这是它通过类型注解驱动运行时行为的一个典型例子——静态类型检查器看到的是类型标注而 Litestar 看到的是数据转换与校验规则。Optional 默认值使其可选bool | None与 None组合使用后done成为可选参数。省略?done时返回全部条目传入?done1时只返回已完成的条目?done0则只返回未完成的条目。如果传入既不是布尔真值也不是假值的非法字符串如?donejohnLitestar 会自动返回 400 错误响应无需手写校验逻辑。这一设计是对教程第 1 章“手动校验查询参数”的升级早期版本曾通过手工判断done是否为1/0并抛出HTTPException来模拟校验而最终版本完全交给类型系统驱动。POST /通过data参数接收请求体第二个路由处理器实现条目的新增post(/) async def add_item(data: TodoItem) - list[TodoItem]: TODO_LIST.append(data) return TODO_LIST关键机制在于data参数Litestar 对名为data的函数参数有特殊识别逻辑它表示“请从请求体中提取数据注入此参数”。这一约定属于框架内置的注入规则类似于FromQuery/FromPath对参数的分类但更隐式——名字本身就决定了注入来源。类型注解TodoItem承担双重职责一方面告诉 Litestar请求体的期望格式是 JSON另一方面规定了反序列化的目标结构。收到 JSON 请求体后Litestar 会将其解析并构造出一个TodoItemdataclass 实例再作为data传入函数体。因为TodoItem是 dataclass字段缺失比如省略title会触发校验错误并返回带详细提示的错误响应比使用裸dict时更加健壮——这一点在教程第 2 章的 Swagger 交互截图对比中有直观体现。配套的测试 tests/examples/test_todo_app.py 验证了这一行为client.post(/, json{title: foo, done: True})返回 201 状态码且TODO_LIST末尾追加了等值的TodoItem(titlefoo, doneTrue)。PUT /{item_title:str}路径参数与请求体的组合第三个路由处理器负责更新已有条目同时用到了路径参数和请求体put(/{item_title:str}) async def update_item(item_title: FromPath[str], data: TodoItem) - list[TodoItem]: todo_item get_todo_by_title(item_title) todo_item.title data.title todo_item.done data.done return TODO_LIST路径模式中的占位符/{item_title:str}是动态路径声明花括号内定义了路径上的“槽位”:str后缀声明该槽位的类型为字符串。于是对路径/Start writing TODO list的PUT请求会命中此处理器并捕获Start writing TODO list作为参数值。litestar内部的路由匹配正是通过这种模式与请求路径做匹配路由解析实现在 litestar/_asgi/routing_trie 目录中。FromPath与占位符的对应关系处理器声明item_title: FromPath[str]FromPath与FromQuery一样是类型别名FromPath: TypeAlias Annotated[T, PathParameter()]见 litestar/params.py。FromPath告诉 Litestar 该参数来源于 URL 路径而参数名item_title必须与路径占位符{item_title:str}中的名称一一对应这样捕获到的值才会注入该参数。类型转换与路径参数类型路径参数同样支持转换与校验:str声明值按字符串处理若写成{item_id:int}Litestar 会尝试把捕获的路径片段转换为整数转换失败则返回错误。完整的受支持类型列表可参考 docs/usage/routing/parameters.rst 中的路径参数类型一节。数据更新与异常处理处理器内部先调用辅助函数get_todo_by_title在TODO_LIST中查找目标条目def get_todo_by_title(todo_name: str) - TodoItem: for item in TODO_LIST: if item.title todo_name: return item raise NotFoundException(detailfTODO {todo_name!r} not found)找不到时抛出NotFoundException继承自HTTPExceptionLitestar 会据此返回 404 状态码和错误消息而不是让请求落入默认 500 错误。找到后用请求体data里的新值覆盖条目的title与done字段并返回更新后的完整列表。对应测试 tests/examples/test_todo_app.py 执行了client.put(/Profit, json{title: Profit, done: True})并断言返回 200 且第三个条目的done变为True。注册应用实例Litestar([...])最后一步是把三个处理器注册进应用app Litestar([get_list, add_item, update_item])Litestar类实现于 litestar/app.py是整个应用的入口与核心容器。它的第一个位置参数接收路由处理器列表——get_list、add_item、update_item这三个由装饰器包装过的函数会依次被注册为路由。此时三个处理器虽共享/与/{item_title:str}等路径但各自绑定不同的 HTTP 方法GET、POST、PUTLitestar 会根据方法 路径的组合路由请求互不冲突应用的 OpenAPI 文档、请求校验、序列化规则均在实例化时基于处理器签名自动构建无需任何额外配置。从源码结构看Litestar([...])内部会为每个处理器创建对应的RouteHandler并交由路由层统一注册这也是后续启动服务时一切请求分发的基础。运行组装好的应用应用组装完成后即可对外提供服务。Litestar 本身不实现 HTTP 协议而是遵循 ASGI 协议将协议层交给 uvicorn 之类的 ASGI 服务器处理。教程第 0 章安装的是标准包litestar[standard]其中已附带 uvicorn 与 Litestar CLI因此可以直接运行litestar runlitestar run会自动识别当前目录下的app.py及其中的Litestar实例无需手动指定模块路径。应用默认监听http://127.0.0.1:8000/届时可用浏览器访问GET /或用 curl 等工具测试POST与PUT请求。开发迭代阶段可使用热重载模式每次保存代码后服务器自动重启litestar run --reloadCLI 的完整能力说明可参考 docs/usage/cli.rst。运行后的应用行为有仓库测试背书tests/examples/test_todo_app.py中full_app模块直接以TestClient驱动上述三个路由的增、查、改场景并断言响应状态码与返回数据可作为你本地验证应用行为的参考范式。小结与下一步至此一个具备完整增、查、改能力的 TODO 应用组装完成。回顾整个装配过程三条核心经验值得记住HTTP 方法决定处理器角色get/post/put等装饰器即方法声明同路径可共存多个不同方法的处理器类型注解即配置FromQuery[bool | None]、FromPath[str]、data: TodoItem分别声明了参数来源、转换规则与校验约束运行时行为完全由签名驱动一处注册、全局生效把处理器列表交给Litestar([...])路由、校验、序列化与 OpenAPI 文档一次性全部就位litestar run即可启动。本教程覆盖的是 Litestar 的基础概念。若想深入理解路由处理器、参数注入、请求/响应处理、依赖注入等机制的完整细节可继续阅读 docs/usage/index.rst 使用指南以及本仓库的 路由参数文档 与 应用生命周期文档。【免费下载链接】litestarLight, flexible and extensible ASGI framework | Built to scale项目地址: https://gitcode.com/GitHub_Trending/li/litestar创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表