Generic pydantic model causes inconsistent OpenAPI spec generation #7960
Replies: 9 comments
-
As of pydantic v1, there is support for overriding the naming behavior of a generic class; see bottom of the section on generic models in the docs https://pydantic-docs.helpmanual.io/usage/models/#generic-models. In the meantime until we have pydantic v1 support, your best bet is probably: ResponseListProjectOut = Response[List[ProjectOut]]
ResponseListProjectOut.__name__ = "Response[List[ProjectOut]]" # or whatever
...
@app.get('/projects', response_model=ResponseListProjectOut)
def get_projects() -> ResponseListProjectOut:
return ResponseListProjectOut(data=[out]) I'm working on a "fix" to the type thing now. PyCharm doesn't make it easy though since it is basically impossible to hide method definitions from it. But I think annotating |
Beta Was this translation helpful? Give feedback.
-
Also have in mind that your path operation function might return something different, like a DB model, a In those cases, you would have to declare the return type of your function as such for Also, you're probably never calling your path operation function directly, FastAPI calls it for you, so you will probably never get a lot of benefit from annotating it's return type. My suggestion is, annotate everything else for your own sanity, but the path operation function... meh, no benefit from that. |
Beta Was this translation helpful? Give feedback.
-
I am quite new to the annotations thing and did think through the implications. Thanks for the hint to skip annotations for the path operations. |
Beta Was this translation helpful? Give feedback.
-
Assuming the original issue was solved, it will be automatically closed now. But feel free to add more comments or create new issues. |
Beta Was this translation helpful? Give feedback.
-
Hello everyone. I have a similar issue to the one presented here. Basically I'm using a pydantic BaseModel to represent the Pagination response. This class extends generic with a TypeVar. T = TypeVar("T")
class PaginationModel(BaseModel, Generic[T]):
total: int = Field(description="Total number of elements on DB")
index: int = Field(description="The current page index")
size: int = Field(description="The size of the page")
results: List[T] Then I use as Generic input the object that should be in the results list class MyMockModel(BaseModel):
foo: int
bar: int Then use it as route response model def get_foo_bar(response_model=PaginationModel[MyMockModel]):
... When I print the openapi spec, I expect to have something like {
"total": 0,
"index": 0,
"size": 20,
"result": [
{
"foo": 0,
"bar": 0
}
]
} but what actually I get is {
"foo": 0,
"bar": 0
} I'm doing somethings wrong, or it is a bug? |
Beta Was this translation helpful? Give feedback.
-
@KiraPC – I just stumbled upon the same issue as you and Google led me here, so I'll write down the solution to that: Instead of deriving your from pydantic import BaseModel
from pydantic.generics import GenericModel
Model = TypeVar("Model", bound=BaseModel)
class PaginationModel(GenericModel, Generic[Model]):
index: int
size: int
total: int
items: List[Model] |
Beta Was this translation helpful? Give feedback.
-
Oh, thank you man. This was very useful. |
Beta Was this translation helpful? Give feedback.
-
Assuming the original need was handled, this will be automatically closed now. But feel free to add more comments or create new issues or PRs. |
Beta Was this translation helpful? Give feedback.
-
Describe the bug
I am wrapping my responses in a generic model like below (full code in toggle section).
I see two issues:
/docs
endpoint renders things differently for a contained list or a contained single element.I am wondering if I am using the
GenericModel
in a wrong way or if there is a bug?Click to toggle
To Reproduce
Expected behavior
Response[List[ProjectOut]]
Screenshots
Environment:
Additional context
Add any other context about the problem here.
Beta Was this translation helpful? Give feedback.
All reactions