FastAPI 进阶:教你 APIRouter 模块化与 Pydantic 实战
前面的笔记我们快速过了一遍 FastAPI 这篇开始将开始细分学习常用的两块内容路由组织 和 请求体。在实际开发当中会遇到两个头疼的问题代码堆积 所有的 API 都写在 main.py 里几百行后根本找不到代码。数据混乱 前端传来的 JSON 格式不对今天这篇内容就是为了解决这两个痛点APIRouter路由组织 与 Pydantic请求体校验。文章目录APIRouter路由一、使用 APIRouter 模块化1、推荐的项目结构2. 编写模块化路由(main.py)3. 业务分流二、Pydantic请求体校验1、定义数据模型2、测试方法用 Swagger 或 Yaak3、Union类型4、嵌套模型APIRouter路由一、使用 APIRouter 模块化当你的项目包含用户、订单、商品等多个模块时APIRouter 就是你的“收纳盒”。1、推荐的项目结构project/├── main.py # 程序入口负责挂载路由├── routers/ # 存放各个模块的逻辑│ ├──init.py│ ├── user.py # 用户相关接口│ └── item.py # 商品相关接口└── schemas/ # 存放数据模型Pydantic Models2. 编写模块化路由(main.py)main.py是整个项目的入口文件所有的请求都会先经过这里只负责初始化和路由挂载利用 ** prefix** 和** tags ** 参数可以极大地减少重复工作fromfastapiimportFastAPI# 导入路由fromaps.Usersimporturls# 1. 初始化路由器app.include_router(urls.api_router,prefix/users,tags[用户管理])tags参数的体现如下图箭头所指3. 业务分流在 分流文件当中不使用 app FastAPI()而是使用 api_router APIRouter()。这样这一组 API 就可以像插件一样随时插拔到主程序上。fromfastapiimportAPIRouter# 路由干三件事路由 “网址 → 函数”的映射表# 看路径/users /login# 看请求方式GET / POST# 决定调用哪个函数# 创建路由api_routerAPIRouter()# 创建功能函数增删改查# 省略了/users 是因为在main函数中路由已经定义了api_router.get(/{id})asyncdefget_user(id:int):return{id:id,name:张三}二、Pydantic请求体校验在这里补充一个表格操作方法查找GET新增POST全改PUT局部改PATCH删除DELETE在处理** POST** 请求时如果字段太多用路径参数显然不现实。这时我们需要 Pydantic 模型来定义数据规范。1、定义数据模型实战代码实现frompydanticimportBaseModel# Pydantic模型定义数据模型进行数据验证和序列化classUser(BaseModel):name:strage:intsalary:floattelephone:strapi_router.post(/add)# 这个异步函数的作用是添加用户接收一个User对象作为参数这个User对象会自动进行数据验证如果数据不符合要求会返回一个错误信息asyncdefadd_user(user:User):print(user)return{name:user.name,age:user.age,salary:user.salary,telephone:user.telephone,message:添加成功}2、测试方法用 Swagger 或 Yaak方法POST路径/addFastAPI 会自动校验name、age、salary、telephone必须有age 必须是整数假如age传入的参数并非整数则返回422错误并且打印哪里错了。如下图当然传入的参数有其他错误时也会报422错误。3、Union类型Union类型在Fastapi里边使用时表示可以接受多种类型的参数fromtypingimportUnion# 而下面具体的函数里面定义了两个参数name和agename是路径参数age是查询参数api_router.get(/search/{name})asyncdefadd_user(name:str,age:Union[int,None]None):print(name,age)return{name:name,age:age}上述使用到的Union则是表示age参数的数据类型可以是int,也可以是None,并且默认是None。而现在多用以下这种表达形式api_router.get(/search/{name})asyncdefadd_user(name:str,height:float|NoneNone):print(name,height)return{name:name,height:height}4、嵌套模型假如用户里有地址只需要多定义一个Address类classAddUser(BaseModel):street:strfloor:intclassUser(BaseModel):name:strage:intsalary:floattelephone:straddress:AddUser这篇就先写到这里内容聚焦在路由组织 请求体基础部分代码是伪代码运行时还需仔细辨别。