如何通过FastAPI和Pydantic向MongoDB存入对象列表?
问题分析与解决
核心问题点
出现422错误主要有三个原因:
- 请求数据格式和接口接收的模型不匹配
- 输入的
price字段类型和模型定义不符 - MongoDB插入方法使用错误
1. 请求格式不匹配
你的ItemList模型要求请求体是包含data字段的对象,但你实际发送的是直接的数组。比如你当前发送的是:
[ {"date": "2022-12-13", "symbol": "nsht", "price": "45.12"}, {"date": "2022-12-13", "symbol": "asdf", "price": "45.14442"} ]
但接口期望的格式是:
{ "data": [ {"date": "2022-12-13", "symbol": "nsht", "price": "45.12"}, {"date": "2022-12-13", "symbol": "asdf", "price": "45.14442"} ] }
如果不想修改请求格式,可直接让接口接收数组,删掉ItemList包裹层即可。
2. 数据类型不匹配
EODCoinModel里price定义为float类型,但请求中传的是字符串(比如"45.12"),FastAPI会因类型不匹配返回422错误。给模型添加验证器即可自动转换:
from pydantic import validator class EODCoinModel(BaseModel): id: PyObjectId = Field(default_factory=PyObjectId, alias="_id") date: str = Field(...) symbol: str = Field(...) price: float = Field(...) @validator('price') def parse_price(cls, v): if isinstance(v, str): return float(v) return v class Config: allow_population_by_field_name = True arbitrary_types_allowed = True json_encoders = {ObjectId: str} schema_extra = { "example": { "date": "2022-12-13", "symbol": "AAPL", "price": 45.12 } }
3. MongoDB插入方法错误
你要插入多个文档,需用insert_many而非insert_one(后者仅支持单文档插入)。同时返回逻辑也需调整,因为插入多个文档后,返回结果不是单个文档结构。
修正后的完整代码
模型部分(直接接收数组)
from pydantic import BaseModel, Field, validator from bson import ObjectId, PyObjectId from typing import List class EODCoinModel(BaseModel): id: PyObjectId = Field(default_factory=PyObjectId, alias="_id") date: str = Field(...) symbol: str = Field(...) price: float = Field(...) @validator('price') def parse_price(cls, v): if isinstance(v, str): return float(v) return v class Config: allow_population_by_field_name = True arbitrary_types_allowed = True json_encoders = {ObjectId: str} schema_extra = { "example": { "date": "2022-12-13", "symbol": "AAPL", "price": 45.12 } }
POST接口部分
from fastapi import FastAPI, Body, status from fastapi.responses import JSONResponse from typing import List from motor.motor_asyncio import AsyncIOMotorClient from fastapi.encoders import jsonable_encoder app = FastAPI() client = AsyncIOMotorClient("mongodb://localhost:27017") db = client["your_database_name"] # 替换为你的数据库名 @app.post("/", response_description="Add new coins", response_model=List[EODCoinModel]) async def create_coins(coins: List[EODCoinModel] = Body(...)): # 转换为MongoDB可存储的格式 coins_data = [jsonable_encoder(coin, by_alias=True) for coin in coins] # 批量插入文档 result = await db["coin"].insert_many(coins_data) # 获取所有插入的文档 created_coins = await db["coin"].find({"_id": {"$in": result.inserted_ids}}).to_list(length=None) return JSONResponse(status_code=status.HTTP_201_CREATED, content=created_coins)
测试请求
现在直接发送你原来的数组格式请求,FastAPI就能正确解析并批量插入到MongoDB中。
内容的提问来源于stack exchange,提问作者Eric.P
相关产品推荐
相关产品推荐

