FastAPI注册用户接口触发RecursionError递归深度超出错误求助
FastAPI注册用户接口触发RecursionError递归深度超出错误求助
嘿,我来帮你排查这个递归错误的问题!这种情况我之前做FastAPI项目时也碰到过,大概率是踩了ORM模型和Pydantic模型混用的坑,先给你拆解下原因和解决方案:
首先,先说说最常见的触发原因:你是不是把SQLAlchemy的Users ORM模型直接当请求体或者返回类型用在接口里了? 很多新手刚开始写FastAPI时都会犯这个错——ORM模型内部藏了很多和数据库会话、关联关系相关的属性,FastAPI在序列化/解析的时候会递归遍历这些属性,直接就把递归深度拉满触发错误了,和你代码里有没有显式写递归调用没关系。
接下来给你一步步修正的方案,结合你的代码来改:
1. 先补全并修正ORM模型
你代码里的Users类字段没写完,先把它补全成正确的ORM模型:
class Users(Base): __tablename__ = 'users' user_id = Column(Integer, primary_key=True, index=True) username = Column(String, unique=True, index=True, nullable=False) hashed_password = Column(String, nullable=False) # 可以加其他你需要的字段,比如邮箱、创建时间之类的
2. 单独定义Pydantic请求/响应模型
必须把接收请求的模型和ORM模型分开,绝对不能混用!比如注册接口的请求体用这个:
from pydantic import BaseModel, Field class CreateUserRequest(BaseModel): username: str = Field(..., min_length=3, max_length=50) password: str = Field(..., min_length=6) # 这里放注册时需要用户提交的字段,比如邮箱之类的 # 注意:请求体模型不用开orm_mode,因为是接收前端参数,不是从ORM实例转换 class Config: orm_mode = False
如果需要返回用户信息,再单独写个响应模型,避免返回敏感字段(比如哈希密码):
class UserResponse(BaseModel): user_id: int username: str class Config: orm_mode = True # 这个是用来从ORM实例转Pydantic模型的
3. 修正注册接口的写法
把接口里的请求体换成刚才定义的Pydantic模型,同时确保密码哈希的逻辑正确,还有数据库会话的依赖函数要写对:
# 先初始化密码上下文和FastAPI实例 pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") app = FastAPI() # 启动时自动创建数据库表 Base.metadata.create_all(bind=engine) # 数据库会话依赖,这个写法是标准的,别写错 def get_db(): db = SessionLocal() try: yield db finally: db.close() # 密码哈希工具函数 def hash_password(password: str) -> str: return pwd_context.hash(password) # 注册接口的正确写法 @app.post("/register_user", response_model=UserResponse) def register_user(user: CreateUserRequest, db: Session = Depends(get_db)): # 先检查用户名是否已存在 existing_user = db.query(Users).filter(Users.username == user.username).first() if existing_user: return {"error": "该用户名已被注册"} # 或者用FastAPI的HTTPException返回400错误 # 创建用户实例,注意用哈希后的密码 new_user = Users( username=user.username, hashed_password=hash_password(user.password) ) # 写入数据库 db.add(new_user) db.commit() db.refresh(new_user) # 刷新实例获取数据库自动生成的user_id # 返回用Pydantic响应模型,自动过滤掉敏感字段 return new_user
其他可能的排查点
如果按照上面改了还是有问题,再检查这两个地方:
- 看看你的
get_db依赖函数有没有不小心递归调用自己,比如函数内部又写了db = get_db(),这种低级错误偶尔也会犯 - 如果你的
Users模型有自关联或者双向关联(比如用户和用户组的双向绑定),在Pydantic响应模型里要排除循环引用的字段,比如用exclude={"group"}或者在字段里加Optional
这样改完之后,你再去localhost:8000/docs里调用接口,应该就不会触发递归错误了。
备注:内容来源于stack exchange,提问作者mraabhijit
相关产品推荐
相关产品推荐

