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スキーマを生成し、適切な場所に配置します。
適切な場所は次のとおりです。
content
キーには、値として別のJSONオブジェクト(dict
)が含まれています。- メディアタイプ(例:
application/json
)を持つキーがあり、その値として別のJSONオブジェクトが含まれています。schema
キーがあり、その値はモデルからのJSONスキーマであり、これが適切な場所です。- FastAPIは、JSONスキーマを直接含めるのではなく、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
パラメーターを使用して、同じメインレスポンスに異なるメディアタイプを追加できます。
たとえば、image/png
の追加のメディアタイプを追加して、パス操作がJSONオブジェクト(メディアタイプapplication/json
)または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
を宣言し、OpenAPIスキーマ内で直接、その同じレスポンスに関する追加情報をresponses
で宣言できます。
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
を使って使用できます。
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。
description
、headers
、content
(この中に異なるメディアタイプとJSONスキーマを宣言します)、links
など、これをresponses
パラメーター内の各レスポンスに直接含めることができます。