I got a problem using FastAPI and Pydantic . I try to return a list of records based on my Pydantic model.
Here is the SQLAlchemy Metadata:
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),
)
Here is the "corresponding" pydantic model:
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
Here is my route:
@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
Here is the Retrieve operation using the Databases library (SQL Alchemy based)
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)
But when I run this I got bunches of ValidationError
from pydantic saying that:
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)
But what is really strange is that if I loop through the DB records returned by the ORM and manually create instances of the pydantic schema in this way:
@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
Then everything works just as expected and I got the List of CustomLayerResponse
in response.
So I wonder what could be the problem with the "auto" validation from pydantic model (the one provided by the response_model
parameter provided by FastAPI, that I set here as List[CustomLayerResponse]
)?
You data field should use a class that extends both FeatureCollection and BaseModel so that you can set its Config subclass field orm_true to true as well.
I haven't tested this with FeatureCollection it self but something similar happened to me.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.