fastAPI端在创建一个类时,只能使用id而不能使用_id作为字段(当你使用pydantic这不符合它的验证)
而mongodb在数据库中生成的id为_id,且为object类型
那么如何处理输入和输出呢
1 处理输入,在mongodb.insert_one()时,不会增加新的名为id的字段
from pydantic import BaseModel,BeforeValidator,Field,ConfigDict
from typing_extensions import Annotated
from bson import ObjectId
PyObjectId = Annotated[str, BeforeValidator(str)]
class DBClass(BaseModel):
id:PyObjectId=Field(alias="_id",default_factory=ObjectId)
name:str
@staticmethod
def transform_input(doc):
doc_dict=DBClass.model_validate(doc).model_dump(by_alias=True)
return doc_dict
插入数据库时,调用方法处理输入
data=[DBClass.transform_input(doc) for doc in input_list]
results=_db_collection.insert_many(data)
2 处理输出,在mongodb.find()时,从API返回的id不再是_id
from pydantic import BaseModel,BeforeValidator,Field,ConfigDict
from typing_extensions import Annotated
from bson import ObjectId
PyObjectId = Annotated[str, BeforeValidator(str)] # 自动将ObjectId转为字符串
from types import SimpleNamespace
class DBClass(BaseModel):
id:PyObjectId=Field(alias="_id",default_factory=ObjectId)
name:str
model_config = ConfigDict(
extra="ignore",
json_encoders={ObjectId: str},
populate_by_name=True
)
#重点,封装方法解析
@staticmethod
def transform(doc):
mapping = {'name': 'db_name'}
# 映射规则,返回的属性为db_name
kwargs = {mapping.get(k, k): v for k, v in doc.items()}
#通过model_dump(by_alias=False)不指定别名输出,此时输出结果为dict
#model_dump(by_alias=False)的作用:键名会保留模型的原始字段名(而非别名)
data_dict=DBClass(**kwargs).model_dump(by_alias=False)
#通过SimpleNamespace类,将上述字典解包到
SimpleNamespace
后,对象的属性名会 完全继承字典的键名data_obj=SimpleNamespace(**data_dict)
return data_obj
3 如果没有其他字段映射,可以这样写
@staticmethod
def tranform(doc):
data_dict=DBClass.model_validate(doc).model_dump(by_alias=False)
data_obj=SimpleNamespace(**data_dict)
return data_obj
这样,在转换返回值的时候,调用类中的 transform方法,可以获得需要的返回值
doc= _db_settings_collection.find_one({"_id":ObjectId(id)})
docF=DBClass.transform(doc)