FastAPI 指南 FastAPI 完全指南(零基础到实战)本文系统梳理 FastAPI 框架的核心知识,涵盖框架介绍、环境搭建、路由、参数验证、请求响应、ORM、中间件、CORS 以及项目结构。所有代码基于 Python 3.12 + FastAPI 0.115,可直接运行。一、FastAPI 介绍1.1 【What】FastAPI 是什么FastAPI 是一个现代、高性能的 Python Web 框架,用于构建 API。它基于Starlette(异步 Web 框架)和Pydantic(数据验证库),结合了异步编程和类型提示,兼顾开发效率与运行性能。官方文档:https://fastapi.tiangolo.com源码:https://github.com/tiangolo/fastapi前端类比:如果你写过 Express.js 或 Koa,FastAPI 就相当于 Python 版的 Express——都是轻量级、高性能的 Web 框架。但 FastAPI 比 Express 更强大:它内置了数据校验(类似 Joi/Zod)、自动生成接口文档(类似 Swagger),还支持异步(async/await)。1.2 【Why】为什么选择 FastAPI核心优势:高性能:基于异步 I/O,性能接近 Node.js 和 Go。使用 Uvicorn(ASGI 服务器),支持高并发请求。性能对比(基于 TechEmpower 等基准测试,简化为每秒请求数):FastAPI:约 3000 请求/秒(异步,轻量)Flask:约 1000 请求/秒(同步,受 WSGI 限制)Django:约 800 请求/秒(同步,ORM 和中间件开销较大)类型提示提升开发效率:FastAPI 使用 Python 类型提示(通过 Pydantic)进行数据验证,减少手动校验代码。类型提示使代码更易读,IDE(如 VSCode)提供自动补全和错误提示。自动生成 API 文档:FastAPI 内置 Swagger UI 和 ReDoc,自动生成交互式 API 文档。开发者只需编写代码,文档即自动生成,减少维护成本。异步支持:支持async/await语法,适合高并发场景(如实时聊天、流处理)。比传统同步框架(如 Flask)更适合现代 Web 应用。为什么选择 FastAPI?开发速度快:类型提示和自动文档减少重复工作。性能优异:异步架构支持高并发,适合生产环境。社区活跃:快速增长的生态,兼容 Starlette 和 Pydantic 的扩展。易于上手:Python 开发者只需掌握基本类型提示即可快速构建 API。1.3 【How】示例:定义一个带类型提示的 API 端点# 从 fastapi 包中导入 FastAPI 类fromfastapiimportFastAPI# 从 pydantic 包中导入 BaseModel,用于定义数据模型frompydanticimportBaseModel# 创建 FastAPI 应用实例app=FastAPI()# 定义一个数据模型 Item,继承自 BaseModelclassItem(BaseModel):name:str# 商品名称,字符串类型,必填price:float# 商品价格,浮点数类型,必填is_offer:bool=None# 是否优惠,布尔类型,可选,默认值为 None# 定义一个 POST 请求的接口,路径为 /items/@app.post("/items/")asyncdefcreate_item(item:Item):# FastAPI 会自动验证请求体中的 name、price 和 is_offer# 无需手动解析 JSONreturnitem提示:上述代码自动验证请求体中的name(字符串)、price(浮点数)和is_offer(布尔值,可选),无需手动解析 JSON。1.4 CGI / WSGI / ASGI 了解CGI:最早的通用接口,解决服务器与动态内容生成程序的通信问题,但性能低下。WSGI:针对 Python 生态优化,取代 CGI,成为 Python Web 开发的主流标准,专注于同步 Web 应用。ASGI:WSGI 的升级,适应异步编程和现代 Web 需求(如 WebSocket、HTTP/2),兼容 WSGI 应用。三者关系用生活例子解释:CGI就像每次客人点菜都要重新建一个厨房(每个请求启动一个新进程),非常慢。WSGI就像一个固定厨房,多个厨师(线程/进程)轮流做菜,效率提升了,但一次只能做一道菜(同步)。ASGI就像一个智能厨房,多个厨师可以同时做多道菜(异步),还能边做菜边接外卖订单(WebSocket)。1.5 业务场景与重要性项目内容业务场景高性能 API 服务、微服务、实时应用、AI 模型接口Web 后端重要性⭐⭐⭐⭐⭐面试标注★★★★面试题:FastAPI 的核心性能优势主要得益于什么?答:基于异步 I/O 和 Uvicorn ASGI 服务器,支持高并发请求。二、环境搭建2.1 创建虚拟环境虚拟环境隔离项目依赖,避免全局环境冲突。以下使用 conda 工具:# 创建虚拟环境,指定 Python 版本为 3.12conda create-nfastapi_envpython=3.12# 激活虚拟环境conda activate fastapi_env# 退出虚拟环境conda deactivate2.2 安装 FastAPI 及其依赖# 在虚拟环境中安装 FastAPI(包含 standard 额外依赖,如 uvicorn)pipinstall"fastapi[standard]"# 指定版本安装pipinstallfastapi==0.115.12 pipinstalluvicorn==0.34.2提示:fastapi[standard]会自动安装uvicorn、httpx等常用依赖,推荐直接用它。2.3 业务场景与重要性项目内容业务场景项目初始化Web 后端重要性⭐⭐⭐⭐⭐面试标注★★三、第一个 API 与启动项目3.1 第一个 API# 导入 FastAPI 类fromfastapiimportFastAPI# 导入 uvicorn 服务器importuvicorn# 创建 FastAPI 应用实例app=FastAPI()# 定义一个 GET 请求接口,路径为 /@app.get("/")defread_root():# 返回一个字典,FastAPI 会自动序列化为 JSONreturn{"Hello":"world"}if__name__=='__main__':# 启动服务器# 'main01:app' 表示 main01 模块中的 app 对象# host='0.0.0.0' 表示允许所有 IP 访问# port=8000 表示监听 8000 端口# reload=True 表示代码修改后自动重启uvicorn.run('main01:app',host='0.0.0.0',port=8000,reload=True,debug=True)# 等价命令:uvicorn file_name:object --reload3.2 启动项目的三种方式方式一:运行 Python 脚本python main01.py方式二:使用 uvicorn 命令uvicorn file_name:object--reload方式三:使用 fastapi 调试命令fastapi dev filename.py3.3 访问项目Swagger UI 文档:http://127.0.0.1:8000/docsReDoc 文档:http://127.0.0.1:8000/redocSwagger UI 是交互式文档,可以直接在页面上测试接口;ReDoc 是只读文档,适合阅读。3.4 业务场景与重要性项目内容业务场景项目启动、接口调试Web 后端重要性⭐⭐⭐⭐⭐面试标注★★四、用 AI 生成 API 接口4.1 AI 工具简介AI 工具可以通过自然语言提示生成代码。常用工具:DeepSeek:https://chat.deepseek.com/豆包:https://www.doubao.com/chat/通义:https://www.tongyi.com/qianwen/Kimi:https://kimi.moonshot.cn/4.2 提示示例向 AI 提供以下提示:# 编写一个 FastAPI 的 HelloWorld 程序 # 请为我生成一个 FastAPI 应用程序,功能:返回欢迎消息。AI 生成的代码:fromfastapiimportFastAPIimportuvicorn app=FastAPI()@app.get("/")defread_root():return{"Hello":"world"}4.3 注意事项AI 生成的代码可能存在小错误(如缺少字段约束),需手动检查。4.4 AI 生成代码的局限性缺乏上下文理解:AI 生成的代码可能符合语法,但未必适配实际业务逻辑(如身份验证流程、数据库设计)。难以维护与调试:若只会"复制粘贴",遇到错误或需求变更时将束手无策。部署与运维盲区:AI 通常不涉及服务器配置、性能优化、监控等生产环境关键环节。4.5 核心能力的不可替代性架构设计思维:如何划分模块、设计 REST API、管理依赖关系,需系统性训练。调试与问题定位:理解上下文机制、请求生命周期,才能快速排查异常。安全与性能意识:防止 SQL 注入、XSS 攻击,或优化数据库查询,需人工介入设计。4.6 业务场景与重要性项目内容业务场景快速生成样板代码,但不能替代核心能力Web 后端重要性⭐⭐⭐面试标注★★五、路径参数5.1 【What】什么是路径参数FastAPI 支持使用 Python 字符串格式化语法声明路径参数(变量)。语法:/path/{参数名}5.2 【How】路径参数示例fromfastapiimportFastAPI app=FastAPI()# 路径参数示例 1:固定路径@app.get("/args1/1")defpath_args1():return{"message":"id1"}# 路径参数示例 2:动态路径,但函数不接收参数@app.get("/args2/{id}")defpath_args2():return{"message":"id2"}# 路径参数示例 3:接收路径参数@app.get("/args3/{id}")defpath_args3(id):# 函数的顺序就是路由的顺序return{"message":id}# 路径参数示例 4:指定类型为 int,FastAPI 会自动转换@app.get("/args4/{id}")defpath_args4(id:int):# 如果传入非整数,FastAPI 返回 422 错误return{"message":id}# 路径参数示例 5:多个路径参数@app.get("/args5/{id}/{name}")defpath_args5(id:str,name:str):return{"id":id,"name":name}if__name__=="__main__":importuvicorn uvicorn.run('aaa:app',host="127.0.0.1",port=8000,reload=True)5.3 【Why】为什么路径参数要有类型声明自动类型转换:声明id: int后,FastAPI 会自动把 URL 中的字符串转换为整数。自动校验:如果传入的不是整数,FastAPI 自动返回 422 错误,无需手动写校验代码。文档友好:类型信息会自动体现在 Swagger UI 中。5.4 业务场景与重要性项目内容业务场景RESTful API 中根据 ID 查询资源(如/users/123)Web 后端重要性⭐⭐⭐⭐⭐面试标注★★★面试题:在 FastAPI 中,关于路径参数的说法哪个是正确的?答:路径参数可以自动转换为声明的类型。六、查询参数6.1 【What】什么是查询参数声明的参数不是路径参数时,路径操作函数会把该参数自动解释为查询参数。查询字符串是键值对的集合,这些键值对位于 URL 的?之后,以及分隔。例如:http://127.0.0.1:8000/items/?page=1limit=106.2 【How】查询参数示例fromfastapiimportFastAPI app=FastAPI()# 查询参数示例 1:必填参数@app.get("/query1")defpage_limit(page,limit):# page 和 limit 都是必填,缺少任何一个会返回 422return{"page":page,"limit":limit}# 查询参数示例 2:可选参数@app.get("/query2")defpage_limit2(page,limit=None):# limit 是可选参数,默认值为 Noneiflimit:return{"page":page,"limit":limit}return{"page":page}# 查询参数示例 3:类型注解@app.get("/query3")defpage_limit3(page,limit,info:int):# info 必须是整数类型return{"page":page,"limit":limit,"info":info}# 查询参数示例 4:与路径参数混用@app.get("/query4/{page}")defpage_limit4(page,limit,info:int):# page 是路径参数,limit 和 info 是查询参数return{"page":page,"limit":limit,"info":info}if__name__=="__main__":importuvicorn uvicorn.run('aaa:app',host="127.0.0.1",port=8000,reload=True)6.3 【Why】查询参数和路径参数的区别路径参数:URL 路径的一部分,如/users/123中的123。用于唯一标识资源。查询参数:URL 问号后的键值对,如/users?page=1中的page。用于过滤、排序、分页。6.4 业务场景与重要性项目内容业务场景分页、过滤、搜索、排序Web 后端重要性⭐⭐⭐⭐⭐面试标注★★★面试题:在 FastAPI 中,如果一个查询参数没有设置默认值,它的行为是什么?答:是必填参数,缺少时会返回 422 错误。七、请求体7.1 【What】什么是请求体FastAPI 使用请求体从客户端(例如浏览器)向 API 发送数据。请求体是客户端发送给 API 的数据。发送数据使用 POST(最常用)、PUT、DELETE、PATCH 等操作。7.2 【How】定义请求体模型fromfastapiimportFastAPIfrompydanticimportBaseModel# 定义请求体模型classItem(BaseModel):name:str# 必填,字符串description:str|None=None# 可选,字符串,默认 Noneprice:float# 必填,浮点数app=FastAPI()# POST 请求,接收请求体@app.post("/items/")asyncdefcreate_item(item:Item):# FastAPI 自动将 JSON 请求体解析为 Item 对象returnitem7.3 【Why】为什么要用 Pydantic 模型自动校验:FastAPI 会校验请求体是否符合模型定义,不符合返回 422。类型转换:自动将 JSON 数据转换为 Python 类型。文档自动生成:模型信息自动体现在 Swagger UI 中。7.4 业务场景与重要性项目内容业务场景创建、更新资源的接口Web 后端重要性⭐⭐⭐⭐⭐面试标注★★★★面试题:在 FastAPI 中,请求体通常以什么格式传递给 API 端点?答:JSON 格式的请求体。八、请求参数验证 - Query 方式FastAPI 提供了强大的 Query 参数验证功能,主要通过Query类和 Pydantic 模型实现。8.1 基础验证类型验证:自动将参数转换为声明类型(如 int、str)。fromfastapiimportFastAPI,Query app=FastAPI()@app.get("/items/")defread_items(q:str=Query(None)):# 默认可选return{"q":q}若传入非字符串类型(如/items/?q=123),FastAPI 会自动处理为字符串。若类型不匹配(如 int 参数传入非数字),返回 422 错误。8.2 长度限制字符串长度:通过min_length和max_length限制。@app.get("/items/")defread_items(q:str=Query(None,min_length=3,max_length=50)):return{"q":q}若 q 长度不符合要求(如 q=ab),返回 422 错误。8.3 正则表达式验证格式匹配:使用regex或者pattern参数。@app.get("/items/")defread_items(q:str=Query(None,regex="^fixedquery$")):return{"q":q}仅接受完全匹配fixedquery的输入。8.4 默认值与必填项默认值:通过 Query 的第一个参数设置。@app.get("/items/")defread_items(q:str=Query("default")):return{"q":q}必填参数:使用...(省略号)标记。@app.get("/items/")defread_items(q:str=Query(...,min_length=3)):return{"q":q}若未提供 q,返回 422 错误。8.5 数值范围验证数值限制:通过gt(大于)、lt(小于)等参数。@app.get("/users/")defget_users(age:int=Query(...,gt=0,lt=100)):# age 必须大于 0 且小于 100return{"age":age}若 age 不在 0-100 之间,返回错误。8.6 多值参数(列表)接收多个值:使用 List 类型。fromtypingimportList@app.get("/items/")defread_items(q:List[str]=Query(["default"])):return{"q":q}访问/items/?q=fooq=bar时,q 值为["foo", "bar"]。8.7 别名与元数据别名:解决参数名冲突或提供友好名称。@app.get("/items/")defread_items(q:str=Query(None,alias="item-query")):return{"q":q}需通过/items/?item-query=foo访问。描述信息:通过description参数添加文档说明。@app.get("/items/")defread_items(q:str=Query(None,description="搜索关键词")):return{"q":q}8.8 弃用参数标记弃用:通过deprecated=True。@app.get("/items/")defread_items(q:str=Query(None,deprecated=True)):return{"q":q}在文档中标记该参数已弃用。8.9 业务场景与重要性项目内容业务场景接口参数校验,防止非法输入Web 后端重要性⭐⭐⭐⭐⭐面试标注★★★★面试题:在 FastAPI 中,以下哪种正则表达式验证方式是正确的?答:regex和pattern两者均可。九、请求参数验证 - Path 方式FastAPI 中的 Path 参数验证主要通过Path类和 Pydantic 模型实现。9.1 基础类型验证自动类型转换:FastAPI 根据类型注解自动转换路径参数类型,失败则返回 422 错误。fromfastapiimportFastAPI app=FastAPI()@app.get("/items/{item_id}")defread_item(item_id:int):# 自动验证为整数return{"item_id":item_id}访问/items/123返回{"item_id": 123},但/items/abc会触发 422 错误。9.2 必填与可选强制必填:路径参数默认必填,即使设置 None 也无效。@app.get("/items/{item_id}")defread_item(item_id:int=Path(...)):# 显式声明必填return{"item_id":item_id}未提供item_id时直接报错。9.3 数值范围验证范围限制:通过gt(大于)、lt(小于)等参数限制数值范围。fromfastapiimportPath@app.get("/products/{product_id}")defget_product(product_id:int=Path(...,gt=1000,le=10000)):# 仅接受 1000 product_id = 10000 的值return{"product_id":product_id}9.4 字符串格式验证正则表达式:使用regex或pattern校验字符串格式。@app.get("/credit-cards/{card_no}")defget_card(card_no:str