【问题标题】:Nested Pydantic Model return error with FastAPI : field required (type=value_error.missing)使用 FastAPI 的嵌套 Pydantic 模型返回错误:必填字段 (type=value_error.missing)
【发布时间】:2021-06-28 21:06:24
【问题描述】:

我在使用 FastAPIPydantic 时遇到问题。 我尝试根据我的 Pydantic 模型返回记录列表。

这是 SQLAlchemy 元数据:


from sqlalchemy import MetaData, Table, Column, Integer, JSON, Boolean
from sqlalchemy.sql import expression

metadata = MetaData()

CustomLayers = Table(
    "custom_layers",
    metadata,
    Column("id", Integer, primary_key=True),
    Column("data", JSON),
    Column("is_public", Boolean, default=expression.false()),
    Column("user_id", Integer),
)

这是“对应的”pydantic 模型:

from geojson_pydantic.features import FeatureCollection
from pydantic import BaseModel

class CustomLayerResponse(BaseModel):
    is_public: bool
    data: FeatureCollection
    user_id: int
    id: int

    class Config:
        orm_mode = True

这是我的路线:


@router.get("/", response_model=List[CustomLayerResponse], status_code=status.HTTP_200_OK)
async def retrieve_by_user(user_id: int):
    layer_records = await customlayers_repository.retrieve_by_user_id(user_id)
    return layer_records

这是使用Databases library(基于 SQL Alchemy)的检索操作


async def retrieve_by_user_id(user_id: int):
    query = CustomLayersTable.select().where(user_id == CustomLayersTable.c.user_id)
    return await database.fetch_all(query=query)

但是当我运行这个时,我从 pydantic 那里得到了一堆 ValidationError 说:

response -> 7 -> id
  field required (type=value_error.missing)
response -> 7 -> user_id
  field required (type=value_error.missing)
response -> 7 -> is_public
  field required (type=value_error.missing)
response -> 7 -> data
  field required (type=value_error.missing)

但真正奇怪的是,如果我遍历 ORM 返回的数据库记录并以这种方式手动创建 pydantic 模式的实例:


@router.get("/", response_model=List[CustomLayerResponse], status_code=status.HTTP_200_OK)
async def retrieve_by_user(user_id: int):
    layer_records = await customlayers_repository.retrieve_by_user_id(user_id)
    response = []
    for l in layer_records:
        manual_instance = CustomLayerResponse(data=FeatureCollection.parse_raw(l.get("data")),
                                user_id=l.get("user_id"),
                                id=l.get("id"),
                                is_public=l.get("is_public"))
        response.append(manual_instance)
    return response

然后一切都按预期工作,我得到了CustomLayerResponse 的列表作为响应。

所以我想知道 pydantic 模型的“自动”验证可能是什么问题(由 FastAPI 提供的 response_model 参数提供的验证,我在这里设置为 List[CustomLayerResponse])?

【问题讨论】:

  • @SuperShoot。谢谢你的评论。实际上,这里需要 orm_mode 来从 ORM 模型中读取数据,而不仅仅是从文档中指定的字典:fastapi.tiangolo.com/tutorial/sql-databases/… 但我必须手动执行,因为即使它应该自动工作它也不会,这是我的问题
  • @SuperShoot 好吧。谢谢你。你说得对。我删除了 orm_mode 并且它开始适用于简单字段......但不适用于我的嵌套模型(即:data : FeatureCollection 这是从 geojson_pydantic 库中导入的 pydantic 模型)......我在这个案例是value is not a valid dict (type=type_error.dict)。但是,如果我从 CustomLayerResponse pydantic 模型中删除此字段,那么它就像其他值类型字段的魅力一样
  • @SuperShoot 我想我需要以某种方式进行反序列化,但我无法弄清楚如何以最佳方式执行它......它应该是嵌套 pydantic 模型的用例,但我没有找到在文档中
  • @SuperShoot 我使用 postgresql。我想我需要使用parse_raw(),但没有像我一样手动实例化模型,我无法面对该怎么做?也许这是不可能的……在嵌套模型的情况下,我们必须手动循环并反序列化……但是 pydantic 和 fastapi 都没有处理这种情况听起来很奇怪……
  • asyncpg 将 jsonjsonb 加载为 str (ref)。我找到了this,但不确定如何通过 sqlalchemy 应用它。 aiopg converts to dict by default,但 databases 似乎不支持。

标签: python sqlalchemy fastapi pydantic


【解决方案1】:

您的数据字段应使用同时扩展 FeatureCollection 和 BaseModel 的类,以便您也可以将其 Config 子类字段 orm_true 设置为 true。

我还没有使用 FeatureCollection 自行测试过这个,但类似的事情发生在我身上。

【讨论】:

    猜你喜欢
    • 2022-11-26
    • 2023-01-18
    • 2021-05-18
    • 2021-03-04
    • 1970-01-01
    • 2022-12-17
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    相关资源
    最近更新 更多