FastAPI教程 OpenAPI 中的其他响应

2021-11-08 09:50 更新

警告

这是一个比较高级的话题。

如果您从FastAPI开始,您可能不需要这个。

您可以声明额外的响应,包括额外的状态代码、媒体类型、描述等。

这些额外的响应将包含在 OpenAPI 架构中,因此它们也会出现在 API 文档中。

但是,对于那些你必须确保其他答复你返回一个Response喜欢JSONResponse直接,你的状态代码和内容。

附加响应 model

您可以将参数传递给路径操作装饰器responses。

它接收 a dict,键是每个响应的状态代码,例如200,值是 other ,其中包含每个响应dict的信息。

每个响应dict都可以有一个 key model,包含一个 Pydantic 模型,就像response_model.

FastAPI将采用该模型,生成其 JSON 模式并将其包含在 OpenAPI 中的正确位置。

例如,要使用状态代码404和 Pydantic 模型声明另一个响应Message,您可以编写:

from fastapi import FastAPI
from fastapi.responses import JSONResponse
from pydantic import BaseModel


class Item(BaseModel):
    id: str
    value: str


class Message(BaseModel):
    message: str


app = FastAPI()


@app.get("/items/{item_id}", response_model=Item, responses={404: {"model": Message}})
async def read_item(item_id: str):
    if item_id == "foo":
        return {"id": "foo", "value": "there goes my hero"}
    else:
        return JSONResponse(status_code=404, content={"message": "Item not found"})

笔记

请记住,您必须JSONResponse直接返回。

信息

的model关键不是的OpenAPI的一部分。

FastAPI将从那里获取 Pydantic 模型,生成JSON Schema,并将其放在正确的位置。

正确的地方是:

  • 在 key 中content,它具有另一个 JSON 对象 ( dict)作为值,其中包含:具有媒体类型的键,例如application/json,包含另一个 JSON 对象作为值,其中包含:一个 key schema,它具有模型中的 JSON Schema 的值,这是正确的位置。FastAPI在此处添加对OpenAPI中另一个位置的全局 JSON 模式的引用,而不是直接包含它。这样,其他应用程序和客户端可以直接使用那些 JSON Schemas,提供更好的代码生成工具等。

在 OpenAPI 中为此路径操作生成的响应将是:

{
    "responses": {
        "404": {
            "description": "Additional Response",
            "content": {
                "application/json": {
                    "schema": {
                        "$ref": "#/components/schemas/Message"
                    }
                }
            }
        },
        "200": {
            "description": "Successful Response",
            "content": {
                "application/json": {
                    "schema": {
                        "$ref": "#/components/schemas/Item"
                    }
                }
            }
        },
        "422": {
            "description": "Validation Error",
            "content": {
                "application/json": {
                    "schema": {
                        "$ref": "#/components/schemas/HTTPValidationError"
                    }
                }
            }
        }
    }
}

这些模式被引用到 OpenAPI 模式中的另一个地方:

{
    "components": {
        "schemas": {
            "Message": {
                "title": "Message",
                "required": [
                    "message"
                ],
                "type": "object",
                "properties": {
                    "message": {
                        "title": "Message",
                        "type": "string"
                    }
                }
            },
            "Item": {
                "title": "Item",
                "required": [
                    "id",
                    "value"
                ],
                "type": "object",
                "properties": {
                    "id": {
                        "title": "Id",
                        "type": "string"
                    },
                    "value": {
                        "title": "Value",
                        "type": "string"
                    }
                }
            },
            "ValidationError": {
                "title": "ValidationError",
                "required": [
                    "loc",
                    "msg",
                    "type"
                ],
                "type": "object",
                "properties": {
                    "loc": {
                        "title": "Location",
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "msg": {
                        "title": "Message",
                        "type": "string"
                    },
                    "type": {
                        "title": "Error Type",
                        "type": "string"
                    }
                }
            },
            "HTTPValidationError": {
                "title": "HTTPValidationError",
                "type": "object",
                "properties": {
                    "detail": {
                        "title": "Detail",
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ValidationError"
                        }
                    }
                }
            }
        }
    }
}

主要响应的其他媒体类型

您可以使用相同的responses参数为相同的主响应添加不同的媒体类型。

例如,您可以添加额外的媒体类型image/png,声明您的路径操作可以返回 JSON 对象(具有媒体类型application/json)或 PNG 图像:

from typing import Optional

from fastapi import FastAPI
from fastapi.responses import FileResponse
from pydantic import BaseModel


class Item(BaseModel):
    id: str
    value: str


app = FastAPI()


@app.get(
    "/items/{item_id}",
    response_model=Item,
    responses={
        200: {
            "content": {"image/png": {}},
            "description": "Return the JSON item or an image.",
        }
    },
)
async def read_item(item_id: str, img: Optional[bool] = None):
    if img:
        return FileResponse("image.png", media_type="image/png")
    else:
        return {"id": "foo", "value": "there goes my hero"}

笔记

请注意,您必须FileResponse直接使用 a 返回图像。

信息

除非您在responses参数中明确指定不同的媒体类型,否则 FastAPI 将假定响应具有与主响应类相同的媒体类型(默认application/json)。

但是,如果您指定了一个自定义响应类None作为其媒体类型,FastAPI 将application/json用于具有关联模型的任何其他响应。

组合信息

您也可以从多个地方,包括结合响应信息response_model,status_code以及responses参数。

您可以声明response_model, 使用默认状态代码200(或自定义状态代码,如果需要),然后responses直接在 OpenAPI 架构中声明相同响应的其他信息。

FastAPI将保留来自 的附加信息responses,并将其与模型中的 JSON 模式结合起来。

例如,您可以404使用使用 Pydantic 模型并具有自定义description.

以及带有200使用您的状态代码的响应response_model,但包括自定义example:

from fastapi import FastAPI
from fastapi.responses import JSONResponse
from pydantic import BaseModel


class Item(BaseModel):
    id: str
    value: str


class Message(BaseModel):
    message: str


app = FastAPI()


@app.get(
    "/items/{item_id}",
    response_model=Item,
    responses={
        404: {"model": Message, "description": "The item was not found"},
        200: {
            "description": "Item requested by ID",
            "content": {
                "application/json": {
                    "example": {"id": "bar", "value": "The bar tenders"}
                }
            },
        },
    },
)
async def read_item(item_id: str):
    if item_id == "foo":
        return {"id": "foo", "value": "there goes my hero"}
    else:
        return JSONResponse(status_code=404, content={"message": "Item not found"})

它将全部组合并包含在您的 OpenAPI 中,并显示在 API 文档中:

结合预定义响应和自定义响应

您可能希望有一些适用于许多路径操作的预定义响应,但您希望将它们与每个路径操作所需的自定义响应结合起来。

对于这些情况,您可以使用“解包”一个的Python的技术dict有**dict_to_unpack:

old_dict = {
    "old key": "old value",
    "second old key": "second old value",
}
new_dict = {**old_dict, "new key": "new value"}

在这里,new_dict将包含来自old_dict加上新的键值对的所有键值对:

{
    "old key": "old value",
    "second old key": "second old value",
    "new key": "new value",
}

您可以使用该技术在路径操作中重用一些预定义的响应,并将它们与其他自定义响应结合起来。

例如:

from typing import Optional

from fastapi import FastAPI
from fastapi.responses import FileResponse
from pydantic import BaseModel


class Item(BaseModel):
    id: str
    value: str


responses = {
    404: {"description": "Item not found"},
    302: {"description": "The item was moved"},
    403: {"description": "Not enough privileges"},
}


app = FastAPI()


@app.get(
    "/items/{item_id}",
    response_model=Item,
    responses={**responses, 200: {"content": {"image/png": {}}}},
)
async def read_item(item_id: str, img: Optional[bool] = None):
    if img:
        return FileResponse("image.png", media_type="image/png")
    else:
        return {"id": "foo", "value": "there goes my hero"}

有关 OpenAPI 响应的更多信息

要查看您可以在响应中包含的内容,您可以查看 OpenAPI 规范中的以下部分:

  • OpenAPI 响应对象,它包括Response Object.
  • OpenAPI Response Object,您可以直接在responses参数中的每个响应中包含任何内容。包括description, headers, content(这里面就是你声明了不同的媒体类型和 JSON Schemas), 和links.


以上内容是否对您有帮助:
在线笔记
App下载
App下载

扫描二维码

下载编程狮App

公众号
微信公众号

编程狮公众号