Describe the question
I am using a pydantic.dataclasses.dataclass as a response_model of my fast api route.
from fastapi import FastAPI
from pydantic.dataclasses import dataclass
@dataclass
class Foo:
bar: int
app = FastAPI()
@app.get('/foo', response_model=Foo)
def get_bar() -> Foo:
return Foo(bar=1)
To Reproduce
Steps to reproduce the behavior:
uvicorn app:apppydantic.error_wrappers.ValidationError: 1 validation error
response
__init__() got an unexpected keyword argument '__initialised__' (type=type_error)
Expected behavior
No validation error and serialized json does not contain any keys __initialised__.
Environment:
Possible solution
Add the following to jsonable_encoder in fastapi.encoders:
from dataclasses import is_dataclass, asdict
def jsonable_encoder(
obj: Any,
include: Set[str] = None,
exclude: Set[str] = set(),
by_alias: bool = True,
skip_defaults: bool = False,
include_none: bool = True,
custom_encoder: dict = {},
sqlalchemy_safe: bool = True,
) -> Any:
...
if is_dataclass(obj):
return asdict(obj)
Thank you. Pydantic's dataclasses are not supported yet. They probably will be at some point.
Any updates on this?
Using pydantic BaseModel vs dataclass causes tremendous slowdown as well in my codebase.
@manojlds which one is slower?
馃憤 for this. I have a backend code base that heavily relies on pydantic dataclasses.
Just a thought, the way pydantic dataclasses are handled is by putting the BaseModel subclass at cls.__pydantic_model__, e.g.:
from pydantic.dataclasses import dataclass
from pydantic import BaseModel
@dataclass
class Foobar:
pass
assert issubclass(Foobar.__pydantic_model__, BaseModel)
Could this be solved with a simple:
if isdataclass(cls) and hasattr(cls, "__pydantic_model__"):
cls = cls.__pydantic_model__
Somewhere?
Hi,
I have been trying to get native dataclasses to work, but am still running into issues when the view function returns the dataclass (referenced as response_body)
Error:
pydantic.error_wrappers.ValidationError: 1 validation error for XYZResponse
response
value is not a valid dict (type=type_error.dict)
Code:
@dataclass
class XYZResponse:
X: str
Y: SomeOtherDataclass
Z: int
@app.post(
'/xyz',
response_model=XYZResponse,
)
async def calculate_xyz(r: XYZRequest):
return XYZResponse(...)
Would be helpful if documentation can address this functionality and its possible limitations (given that it is not a BaseModel) of using and mixing the usage of BaseModel and dataclass as Schemas
Is it more likely that tools such as mypy and pyright will opt to do type checking on built-in objects, such as Python's standard dataclasses, vs library-supplied objects, like FastAPI's BaseModel and pydantic.dataclasses?
I think it might. In addition, TypedDict (another built-in come Python 3.8), is already being checked (to varying degrees of success) by the aforementioned type checkers.
@jomido Pydantic v1.1 has a mypy plugin that supports checks for BaseModel including everything supported for dataclasses, and more. You can see the full details here.
(I am confident in this assessment because I wrote the pydantic mypy plugin, and based it largely on the official dataclasses plugin. Also, note BaseModel is actually a pydantic thing, not a FastAPI thing.)
Pydantic dataclasses are also treated by mypy in exactly the same way as built-in dataclasses (except that support for the pydantic-specific config argument was recently added to the pydantic dataclass decorator).
@justinttl It looks like pydantic dataclasses work as long as you provide a config with from_orm=True:
from fastapi import FastAPI
from pydantic.dataclasses import dataclass
from starlette.testclient import TestClient
class ORMConfig:
orm_mode = True
@dataclass(config=ORMConfig)
class XYZResponse:
x: str
app = FastAPI()
@app.get(
'/xyz',
response_model=XYZResponse,
)
async def calculate_xyz():
return XYZResponse("hello")
print(TestClient(app).get("/xyz").content)
# b'{"x":"hello"}'
@tiangolo I feel like there is room for improvement around the handling and/or error messages here. Maybe we should require orm_mode for any model used by FastAPI? Or turn it on automatically?
@samuelcolvin Any ideas about how we might more clearly indicate to users that the problem is coming from orm_mode=False?
I would guess the best approach would be a check in fastapi that orm_mode is enabled, perhaps powered by some pydantic tool methods like get_model or get_config that work on both models and dataclasses?
That's a good idea, I think we should add that check to FastAPI in the near future. In particular, raising an error if a response_model is specified that doesn't have orm_mode = True. Or maybe just if the annotated return type differs from the response_model (so that orm_mode might be explicitly relevant).
Alternatively, perhaps we should automatically enable orm_mode as necessary, possibly by subclassing the provided response_model with an update to the Config. That way we don't introduce errors into any existing code.
agreed with this. I've just hit the same issue - and the logged error ("value is not a valid dict (type=type_error.dict)") is less than informative. The orm_mode fix does work as expected though - so that's good.
This does not work with nested dataclassed. The inner class record will have ...,__intialized__ : true,...
When model is a dataclass - my parameter is being treated as a query, but when I derive it from BaseModel - it is a request body
Most helpful comment
@justinttl It looks like pydantic dataclasses work as long as you provide a config with
from_orm=True:@tiangolo I feel like there is room for improvement around the handling and/or error messages here. Maybe we should require
orm_modefor any model used by FastAPI? Or turn it on automatically?@samuelcolvin Any ideas about how we might more clearly indicate to users that the problem is coming from
orm_mode=False?