概要
前回まででカスタムレスポンスクラスを扱う方法を紹介しました
ただ openapi にレスポンスの XML 情報が掲載されない問題がありました
今回はその問題に対処してみます
環境
- Python 3.11.3
- fastapi 0.100.1
- pydantic-xml 1.0.0
サンプルコード
- vim ./app.py
import textwrap
from typing import Union
from fastapi import FastAPI, Response
from pydantic_xml import BaseXmlModel, element
app = FastAPI()
class User(BaseXmlModel, tag="User"):
name: str = element(tag="Name")
age: int = element(tag="Age")
class XmlResponse(Response):
def __init__(self, content: Union[str, bytes], status_code: int = 200):
super().__init__(content, status_code=status_code, media_type="application/xml")
@app.get(
"/",
response_class=XmlResponse,
response_model=User,
responses={
200: {
"description": "Success",
"content": {
"application/xml": {
"schema": {"$ref": "#/components/schemas/User"},
"example": textwrap.dedent(
"""
<?xml version="1.0" encoding="UTF-8"?>
<User>
<Name>hawk</Name>
<Age>20</Age>
</User>
"""
)[1:-1],
},
"application/json": None,
},
},
},
)
def xml():
result = User(name="hawksnowlog", age=10)
return XmlResponse(content=result.to_xml())
解説
openapi のドキュメントの作成は responses 属性を使って行います
content 配下に application/xml を定義し更に schema と example を定義します
schema に直接 Python のクラスを指定すると ValueError: [TypeError("'ModelField' object is not iterable"), TypeError('vars() argument must have __dict__ attribute')]
というエラーになるので openapi に出力された際にスキーマを参照する形式で指定します
そして example はヒアドキュメントで直接していします
ここが dict などにしていしまうとうまく XML が表示されないので注意が必要です
application/json のレスポンスはデフォルトで表示されてしまうので不要であれば None を指定します
動作確認
-
pipenv run uvicorn app:app --reload
で localhost:8000/docs にアクセスると以下のようにちゃんとレスポンスのサンプルが XML で表示されているのが確認できると思います
最後に
fastapi でXML のレスポンスを扱う場合には最終的には以下の組み合わせがいいかなと思います
- モデルの表現 -> pydantic-xml
- レスポンスの表現 -> Response クラスを継承して XmlResponse クラスを作成する
- ドキュメントの表現 -> responses 属性を使って content に直接 application/xml のレスポンスを定義する
0 件のコメント:
コメントを投稿