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

如何通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 07:45:49