FastAPI+Beanie创建用户遇RevisionIdWasChanged,无法返回重复键提示
问题解决:Beanie创建用户时RevisionIdWasChanged异常导致500错误
异常原因
你遇到的RevisionIdWasChanged是Beanie乐观锁机制触发的异常。调用save()方法时,Beanie会先尝试插入新文档,遇到MongoDB重复键错误后,内部会尝试执行更新操作,但此时文档实际因重复键冲突插入失败,乐观锁的revision_id校验不通过,最终抛出这个异常,覆盖了原本的DuplicateKeyError,导致你捕获不到预期错误。
解决方案
1. 同时捕获两种异常
在路由层同时捕获pymongo.errors.DuplicateKeyError和beanie.exceptions.RevisionIdWasChanged,统一返回400错误:
from beanie.exceptions import RevisionIdWasChanged from pymongo.errors import DuplicateKeyError from fastapi import HTTPException, status @user_router.post('/create', summary="Create new user") async def create_user(data: UserAuth): try: return await UserService.create_user(data) except (DuplicateKeyError, RevisionIdWasChanged): raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="User with this email or username already exists" )
2. 使用插入专用方法替代save()
在UserService.create_user中,改用Beanie的insert()或create()方法(仅执行插入操作,不会触发更新逻辑),从根源避免乐观锁异常:
# user_service.py async def create_user(data: UserAuth): user_in = User(**data.dict()) # 用insert替代save await user_in.insert() return user_in
或者直接用模型的create类方法:
async def create_user(data: UserAuth): return await User.create(**data.dict())
3. 确认唯一索引配置
确保User模型中已为邮箱和用户名设置唯一索引,这样MongoDB才会触发重复键错误:
from beanie import Document, Indexed from pydantic import EmailStr class User(Document): username: Indexed(str, unique=True) email: Indexed(EmailStr, unique=True) # 其他字段...
如果是已存在的集合,需手动在MongoDB Atlas创建唯一索引,或通过Beanie初始化索引:
# 应用启动时执行 await User.create_indexes()
内容的提问来源于stack exchange,提问作者user23188487
相关产品推荐
相关产品推荐

