使用Beanie与FastAPI时触发CollectionWasNotInitialized错误的问题
解决Beanie中
CollectionWasNotInitialized错误(嵌套Document类场景) 刚接触Beanie——一款基于Pydantic的MongoDB异步Python ODM,尝试和FastAPI结合使用时遇到了问题。我为SomeClass文档编写了嵌套在SomeClassDao类中的ODM代码,调用插入方法时触发了beanie.exceptions.CollectionWasNotInitialized错误,代码如下(位于someClass.py):
from beanie import Document from pydantic import Field, BaseModel class SomeClassDto(BaseModel): """ A Class for Data Transferring. """ name: str = Field(max_length=maxsize, min_length=1) class SomeClassDao: """ This is a class which holds the 'SomeClass' class (inherited from Beanie Document), and also, the methods which use the 'SomeClass' class. """ class SomeClass(Document): name: str = Field(max_length=20, min_length=1) @classmethod async def create_some_class(cls, body: SomeClassDto): some_class = cls.SomeClass(**body.dict()) return await cls.SomeClass.insert_one(some_class)
调用create_some_class方法向数据库插入数据时,抛出错误:beanie.exceptions.CollectionWasNotInitialized。
问题原因
Beanie在初始化时需要扫描并注册所有继承自Document的类,以此创建对应的MongoDB集合。但你将SomeClass(继承自Document)嵌套在了SomeClassDao内部,Beanie默认无法扫描到这个嵌套类,因此没有为它初始化集合,导致操作数据库时出错。
解决方案
有两种可行的解决方式:
方案1:将Document类移至顶层
最直接的方式是把嵌套的SomeClass从SomeClassDao中移出,作为顶层类定义,这样Beanie初始化时能自动扫描到它:
from beanie import Document from pydantic import Field, BaseModel class SomeClassDto(BaseModel): """ A Class for Data Transferring. """ name: str = Field(max_length=20, min_length=1) # 修复原代码中未定义的maxsize变量 class SomeClass(Document): name: str = Field(max_length=20, min_length=1) class SomeClassDao: """ This is a class which holds the methods which use the 'SomeClass' class. """ @classmethod async def create_some_class(cls, body: SomeClassDto): some_class = SomeClass(**body.dict()) return await SomeClass.insert_one(some_class)
方案2:显式注册嵌套的Document类
如果需要保留嵌套结构,在Beanie初始化时显式指定要注册的嵌套Document类即可。比如在FastAPI的启动事件中配置:
from beanie import init_beanie from motor.motor_asyncio import AsyncIOMotorClient from fastapi import FastAPI from someClass import SomeClassDao app = FastAPI() @app.on_event("startup") async def startup_db(): # 连接MongoDB client = AsyncIOMotorClient("mongodb://localhost:27017") # 初始化Beanie,显式注册嵌套的SomeClass await init_beanie( database=client.your_database_name, document_models=[SomeClassDao.SomeClass] )
额外提示
原代码中SomeClassDto的max_length使用了未定义的maxsize变量,建议替换为具体数值(比如和SomeClass中一致的20),避免运行时抛出未定义变量的错误。
内容的提问来源于stack exchange,提问作者Behdad Abdollahi Moghadam
相关产品推荐
相关产品推荐

