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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:43:13