You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.16 07:03:00