I have an endpoint that can return JSON or a file (xlsx):
class ReportItemSerializer(BaseModel):
id: int
werks: Annotated[WerkSerializerWithNetwork, Field(validation_alias="werk")]
plu: Annotated[str, Field(description="Название PLU")]
start_date: Annotated[date, None, Field(description="Дата начала периода в формате")]
end_date: Annotated[date | None, Field(description="Дата окончания периода")]
anfmenge: Annotated[int | None, Field(des cription="Запас на начало периода")]
endmenge: Annotated[int | None, Field(description="Остаток по PLU в разрезе поставщика на конец периода")]
soll: Annotated[int, None, Field(description="Поступило за период")]
haben: Annotated[
int | None, Field(description="Количество по PLU, которое было возвращено поставщику за указанный период")]
model_config = ConfigDict(from_attributes=True)
class PaginatedReportItemsSerializer(BaseModel):
count: int
results: list[ReportItemSerializer]
@router.get(
"/orders/report",
responses={
200: {
"description": "Return report",
"content": {
"application/json": {
"schema": PaginatedReportItemsSerializer.schema(ref_template="#/components/schemas/{model}")
},
"application/octet-stream": {}
},
},
}
)
async def get_report():
pass
With this I have a problem with swagger. With configuration above there is problem:
Nested ReportItemSerializer
is not being displayed (string
is instead displayed).
How can I fix it?
Here is a working example, heavily based on this answer—hence, please have a look at that answer for more details.
The example below will correctly display the example value/schema in Swagger UI autodocs, under the 200
response's description. Using the drop down menu, one could switch between the various media types; in this case, that is application/json
and application/octet-stream
.
from fastapi import FastAPI
from fastapi.openapi.constants import REF_PREFIX
from pydantic import BaseModel
from datetime import datetime
class SubMessage(BaseModel):
msg: str
dt: datetime = None
class Message(BaseModel):
msg: str
sub: SubMessage
def get_200_schema():
return {
'model': Message,
'content': {
'application/json': {
'schema': {'$ref': REF_PREFIX + Message.__name__}
},
'application/octet-stream': {
'schema': {} # whatever
}
},
}
app = FastAPI()
@app.get('/', responses={200: get_200_schema()})
async def get_msg():
return Message(msg='main msg', sub=SubMessage(msg='sub msg', dt=datetime.now()))