OpenAPIにおける追加レスポンス¶
警告
これはかなり高度なトピックです。
FastAPIを使い始めたばかりの場合、これは必要ないかもしれません。
追加のステータスコード、メディアタイプ、説明などを使用して、追加のレスポンスを宣言できます。
これらの追加レスポンスはOpenAPIスキーマに含まれるため、APIドキュメントにも表示されます。
ただし、これらの追加レスポンスについては、ステータスコードとコンテンツを含むJSONResponse
のようなResponse
を直接返すようにする必要があります。
model
を使った追加レスポンス¶
パス操作デコレータにresponses
パラメータを渡すことができます。
これはdict
を受け取ります。キーは各レスポンスのステータスコード(200
など)、値はそれぞれの情報を持つ別のdict
です。
これらのレスポンスdict
にはそれぞれ、response_model
と同様に、Pydanticモデルを含む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"}
return JSONResponse(status_code=404, content={"message": "Item not found"})
注意
JSONResponse
を直接返す必要があることに注意してください。
情報
model
キーはOpenAPIの一部ではありません。
FastAPIはそこからPydanticモデルを取得し、JSONスキーマを生成して、適切な場所に配置します。
適切な場所は次のとおりです。
- 値として別のJSONオブジェクト(
dict
)を持つcontent
キーに。- メディアタイプ(例:
application/json
)を持つキー。値として、別のJSONオブジェクトを持つ。- キー
schema
。値としてモデルからのJSONスキーマがあります。ここが正しい場所です。- FastAPIは、直接含める代わりに、ここでOpenAPI内の別の場所にあるグローバルJSONスキーマへの参照を追加します。これにより、他のアプリケーションやクライアントはこれらのJSONスキーマを直接使用でき、より優れたコード生成ツールなどを提供できます。
- キー
- メディアタイプ(例:
このパス操作の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
パラメータを使用して、同じメインレスポンスに対して異なるメディアタイプを追加できます。
たとえば、パス操作がJSONオブジェクト(メディアタイプapplication/json
)またはPNG画像を返すことができると宣言することで、image/png
の追加メディアタイプを追加できます。
from typing import Union
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: Union[bool, None] = None):
if img:
return FileResponse("image.png", media_type="image/png")
else:
return {"id": "foo", "value": "there goes my hero"}
注意
FileResponse
を直接使用して画像を返す必要があることに注意してください。
情報
responses
パラメータで別のメディアタイプを明示的に指定しない限り、FastAPIは、レスポンスがメインレスポンスクラス(デフォルトapplication/json
)と同じメディアタイプを持つと想定します。
ただし、メディアタイプとしてNone
を持つカスタムレスポンスクラスを指定した場合、FastAPIは、関連付けられたモデルを持つ追加レスポンスにapplication/json
を使用します。
情報の組み合わせ¶
response_model
、status_code
、responses
パラメータを含む、複数の場所からのレスポンス情報を組み合わせることもできます。
デフォルトのステータスコード200
(または必要に応じてカスタムのステータスコード)を使用してresponse_model
を宣言し、responses
でその同じレスポンスの追加情報をOpenAPIスキーマに直接宣言できます。
FastAPIは、responses
からの追加情報を保持し、モデルからのJSONスキーマと組み合わせます。
たとえば、Pydanticモデルを使用し、カスタムのdescription
を持つステータスコード404
を持つレスポンスを宣言できます。
また、response_model
を使用するが、カスタムのexample
を含むステータスコード200
を持つレスポンスを宣言できます。
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_to_unpack
でdict
を「展開」することができます。
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 Union
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: Union[bool, None] = None):
if img:
return FileResponse("image.png", media_type="image/png")
else:
return {"id": "foo", "value": "there goes my hero"}
OpenAPIレスポンスに関する詳細情報¶
レスポンスに含めることができる内容を正確に確認するには、OpenAPI仕様の次のセクションを確認してください。
- OpenAPI Responses Object には、
Response Object
が含まれています。 - OpenAPI Response Object では、
responses
パラメータ内の各レスポンスに、description
、headers
、content
(この中では、さまざまなメディアタイプとJSONスキーマを宣言します)、およびlinks
など、ここから直接含めることができます。