FastAPI核心知识点与高频易错点总结

FastAPI核心知识点与高频易错点总结

标签:#FastAPI #Python #后端开发 #接口开发 #踩坑记录

📑 目录导航

前言

FastAPI 是基于 Starlette(ASGI)Pydantic 构建的高性能 Python Web 接口框架。它依托 Python 类型提示,自动完成参数校验与接口文档生成,兼顾开发效率与运行性能。很多新手在参数传递、异步编程、路由设计、数据校验等方面容易踩坑,本文系统梳理核心知识点与高频开发踩坑点,适合快速复习与面试复盘。

一、核心基础知识点

1.底层两大核心库

  1. Starlette:轻量级 ASGI 异步 Web 框架,负责请求接收、路由分发、中间件、WebSocket 等底层通信,天然支持高并发。
  2. Pydantic :数据模型校验库,依靠类型注解完成请求/响应数据的校验与序列化,校验失败时自动返回 422 错误码,无需手写校验逻辑。> 访问内置文档:/docs(Swagger交互式文档)、/redoc(静态文档),无需手写接口文档

2.路由与参数区分

(1)路径参数

路径参数定义在 URL 路径的 {} 中,例如 /user/{user_id}函数参数名必须与花括号内的变量名完全一致 ,否则框架无法正确绑定。```python

from fastapi import FastAPI

app = FastAPI()

@app.get("/user/{user_id}")

def get_user(user_id:int):

return {"id":user_id}

复制代码
#### (2)查询参数
查询参数位于 URL 的 `?` 之后,以 `key=value` 形式传递,多个参数用 `&` 连接。函数中**不在路径大括号内的参数**会被自动识别为查询参数,且通常应设置默认值或声明为可选。```python
@app.get("/search")
def search(keyword:str|None=None):
    return {"kw":keyword}
(3)请求体Post JSON

POST/PUT 等请求的 JSON 请求体,必须使用 Pydantic 的 BaseModel 子类接收。注意:GET 请求没有请求体,不能使用模型接收参数。

python 复制代码
from pydantic import BaseModel

class Item(BaseModel):
    name:str
    price:float

@app.post("/item")
def create_item(item:Item):
    return item

区分记忆:

  • 路径参数:url路径{xxx}
  • 查询参数:url问号后面
  • 请求体:post json,用BaseModel接收

3. defasync def 路由函数(高频考点)

  1. async def:异步函数,内部可以await,适合IO密集操作(异步数据库、http请求),禁止内部写同步阻塞代码(time.sleep、同步数据库),会阻塞事件循环,并发直接垮掉。
  2. def普通同步函数:FastAPI自动丢到线程池运行,适合同步ORM、CPU计算,不会阻塞主循环。

4.依赖注入 Depends(FastAPI灵魂)

用来封装公共逻辑:获取数据库会话、登录鉴权、公共参数解析。

python 复制代码
from fastapi import Depends

def get_db():
    """模拟获取数据库会话"""
    db = "db_session"
    try:
        yield db
    finally:
        print("关闭连接")

@app.get("/demo")
def demo(db = Depends(get_db)):
    return {"db":db}

5.响应模型 response_model

过滤返回字段,做输出序列化,隐藏敏感字段。

python 复制代码
@app.get("/item/{id}",response_model=Item)
def get_item(id:int):
    return {"name":"苹果","price":9.9,"secret":"密钥123"}
# secret字段不会返回给前端

6.跨域中间件CORS

前后端分离必配,否则浏览器拦截请求。

python 复制代码
from fastapi.middleware.cors import CORSMiddleware

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

二、高频易错点(开发踩坑合集)

🚨坑1:422 Unprocessable Entity(最常见)

含义:请求格式正确,但是数据不满足模型/类型校验规则。

常见原因:

  1. Post接口传form‑data,但是后端用Pydantic模型接收(Pydantic只接收application/json)。
  2. 参数类型不匹配:定义int,前端传字符串。
  3. 必传参数没有传递;Optional不等于可选参数,必须加=None才可以不传
python 复制代码
# ❌错误:Optional只是允许为None,不传参依然报错
def test(name:str|None):
    pass

# ✅正确:给默认值None,代表参数可以不传
def test(name:str|None = None):
    pass
  1. Pydantic校验规则不满足(长度、数值范围)。

排查技巧:看返回的detail数组,里面有错误位置与原因;优先在/docs文档页面测试接口。

🚨坑2:路由顺序错误,固定路由被动态路由拦截

固定路径路由必须写在动态路径前面,否则动态参数会优先匹配。

python 复制代码
# ❌错误
@app.get("/user/{user_id}")
def get_uid(user_id:int):...

@app.get("/user/me")
def get_my_info():... #访问/user/me会被上面路由捕获,user_id="me"报422

# ✅正确:固定路由写上方
@app.get("/user/me")
def get_my_info():...

@app.get("/user/{user_id}")
def get_uid(user_id:int):...

🚨坑3:async def内部写同步阻塞代码

python 复制代码
import time
# ❌灾难写法,阻塞事件循环,所有请求全部卡住
@app.get("/bad")
async def bad_demo():
    time.sleep(2)
    return {}

# ✅方案1:改成普通def,交给线程池
@app.get("/good1")
def good_demo():
    time.sleep(2)
    return {}

# ✅方案2:使用异步sleep
import asyncio
@app.get("/good2")
async def good_demo2():
    await asyncio.sleep(2)
    return {}

🚨坑4:混淆路径参数与查询参数,参数名不匹配

路由/user/{user_id},函数参数必须叫user_id;如果写id,框架识别不到路径参数,把id当成查询参数,接口直接异常。

🚨坑5:--reload热重载用于生产环境

uvicorn main:app --reload仅本地开发使用;生产环境禁止开启reload,会带来性能与安全隐患,生产使用gunicorn+uvicorn worker部署。

🚨坑6:Pydantic内部普通raise抛出异常返回500

模型校验函数中,不要直接raise ValueError,会返回500服务端错误;需要抛出ValidationError,才返回422参数错误。优先使用Field内置校验规则。

python 复制代码
from pydantic import BaseModel,Field

class Demo(BaseModel):
    num:int = Field(gt=0) #大于0,校验失败返回422

🚨坑7:斜杠歧义 /item/item/

FastAPI会自动重定向,但是项目建议统一路径风格,不要混用末尾斜杠。

🚨坑8:GET接口使用Pydantic接收参数

GET请求没有请求体,Pydantic模型默认读取body,GET接口直接用函数参数接收查询参数。

三、排错小技巧

  1. 优先访问/docs在文档页面测试接口,复现问题。
  2. 出现422,读取返回json的detail字段,定位哪个字段出错。
  3. 异步接口卡住,优先检查内部是否存在同步阻塞IO。
  4. 跨域报错,确认CORS中间件配置,中间件添加位置在app = FastAPI()之后,路由之前。

四、总结

  1. FastAPI依靠类型提示,同时完成校验、文档生成;不要省略类型注解,否则校验、文档全部失效。
  2. 分清路径参数、查询参数、请求体,GET没有body,POST使用Pydantic模型接收JSON。
  3. 路由顺序:固定路由写动态路由上方。
  4. async def慎用,内部不要写阻塞同步代码;Optional需要搭配=None实现参数可选。
  5. 开发用--reload,生产环境务必关闭。

配套代码仓库可以把文中示例复制运行,快速复现各个坑点加深理解。


相关推荐
HugoStudio_SWAN1 小时前
洛谷 P1319 / P1320 压缩技术——同一枚硬币的正反面
c++·学习·程序人生·算法
λqaq72 小时前
MongoDB数据库基础 :非关系型数据库入门与常用操作
数据库·学习·mongodb·nosql
凯尔萨厮2 小时前
Java学习笔记十四(网络通信)
笔记·学习
AAA代码批发商2 小时前
DAYS 38 TCP并发服务器模型详解
linux·网络·笔记·学习
zyf1044162 小时前
暑期实践日志 Day46:复盘第六章,规整对应实践成果
学习·计算机网络·剪辑·暑期实践·课题任务
wdfk_prog3 小时前
canopennode-rtt推荐,不只可以做从站,也可以承担主站角色
c语言·开发语言·数据库·学习·算法·深度优先
边境悍匪3 小时前
蜗牛学苑 Java 智能体学习 Day34|AOP 进阶、权限思维导图复盘
java·开发语言·spring boot·学习
UIU1143 小时前
CPU、RAM与外设寄存器
学习
tju新生代魔迷3 小时前
Verilog HDL 学习笔记(十二)| 第12章 用户自定义原语(UDP)
笔记·学习·udp