【发布时间】:2021-06-28 21:06:24
【问题描述】:
我在使用 FastAPI 和 Pydantic 时遇到问题。 我尝试根据我的 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 将
json和jsonb加载为str(ref)。我找到了this,但不确定如何通过 sqlalchemy 应用它。 aiopg converts to dict by default,但databases似乎不支持。
标签: python sqlalchemy fastapi pydantic