如何在 FastAPI 中将字典列表作为 Body 参数发送?

Posted

技术标签:

【中文标题】如何在 FastAPI 中将字典列表作为 Body 参数发送?【英文标题】:How Do I send list of dictionary as Body parameter in FastAPI? 【发布时间】:2020-11-16 12:28:53 【问题描述】:

在 FastAPI 中传递字典列表,一般我们会定义一个 pydantic 模式并提及为

param: List[schema_model]

我面临的问题是我的请求中有要附加的文件。我找不到在路由器功能中定义架构和文件上传的方法。为此,我将所有参数(请求正文)定义为 Body 参数,如下所示。

@router.post("/", response_model=DataModelOut)
async def create_policy_details(request:Request,
    countryId: str = Body(...),
    policyDetails: List[dict] = Body(...),
    leaveTypeId: str = Body(...),
    branchIds: List[str] = Body(...),
    cityIds: List[str] = Body(...),
    files: List[UploadFile] = File(None)
    ):

当我使用邮递员的表单数据选项发送请求时,它显示 policyDetails 参数的“0:value is not a valid dict”。我正在发送 ["name":"name1","department":"d1"]。它说不是一个有效的字典,即使我发送了有效的字典。谁可以帮我这个事? DataModelOut 类

class DataModelOut(BaseModel):
    message: str = ""
    id: str = ""
    input_data: dict = None
    result: List[dict] = []
    statusCode: int

【问题讨论】:

你好 samba 可以添加 DataModelOut 类吗? 我认为 DataModelOut 会影响响应。我对请求有疑问。我被添加了 我只使用 policyDetails 创建了请求,效果很好。 【参考方案1】:

问题直接来自response_model,而你的返回值,假设我有一个这样的应用

class Example(BaseModel):
    name: str 
    
@app.post("/", response_model=Example)
async def example(value: int):
    return value

现在我正在向它发送请求

pydantic.error_wrappers.ValidationError: 1 validation error for Example
response
  value is not a valid dict (type=type_error.dict)

错误和你的一样。即使我发送相同的参数,它也会引发相同的错误

class Example(BaseModel):
    name: int 
    other: int

@app.post("/", response_model=Example)
async def example(name: int, other: int):
    return name

Out:   value is not a valid dict (type=type_error.dict)

但如果我像这样声明查询参数(来自docs 的最佳实践)它会工作得很好。

class Example(BaseModel):
    name: int 
    other: int

@app.post("/", response_model=Example)
async def example(ex: Example = Body(...)):
    return ex

Out: 
"name": 0,
"other": 0

在您的情况下,您可以创建两个单独的模型,DataModelInDataModelOut

class DataModelOut(BaseModel):
    message: str = ""
    id: str = ""
    input_data: dict = None
    result: List[dict] = []
    statusCode: int
    
class DataModelIn(BaseModel):
    countryId: str 
    policyDetails: List[dict]
    leaveTypeId: str 
    branchIds: List[str]
    cityIds: List[str]


@app.post("/", response_model=DataModelOut)
async def create_policy_details(data: DataModelIn = Body(...)):
    return "input_data":data,
            "statusCode":1

现在我正在向它发送请求

Out: 
  "message": "",
  "id": "",
  "input_data": 
    "countryId": "30",
    "policyDetails": [
      
        "some": "details"
      
    ],
    "leaveTypeId": "string",
    "branchIds": [
      "string"
    ],
    "cityIds": [
      "string"
    ]
  ,
  "result": [],
  "statusCode": 1

它就像一个魅力。您也可以使用response_model_exclude_unset=True 参数从响应中丢弃messageid,也可以检查this out

【讨论】:

【参考方案2】:

我认为您应该在 Schema/Model 类中添加一个配置类,并将 orm_mode 设置为 True

    class DataModelOut(BaseModel):
       message: str = ""
       id: str = ""
       input_data: dict = None
       result: List[dict] = []
       statusCode: int
       
       class Config:
         orm_mode=True

【讨论】:

以上是关于如何在 FastAPI 中将字典列表作为 Body 参数发送?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Python中将json.loads作为列表而不是字典[重复]

fastapi教程翻译(七):Body - 多种参数

如何在Python中将dict元素值作为列表

如何在Python中将字符串列表转换为字典列表[重复]

如何在 Python 中将两个列表组合成字典? [复制]

如何在ansible中将字典或列表转换为字符串