🆎
【FastAPI】バリデーションエラーメッセージを日本語化
バリデーションエラーメッセージを日本語化したい
Pydanticでバリデーションエラーメッセージをカスタマイズ
FastAPIでバリデーションエラーメッセージを日本語にしたくて、
FastAPIの公式ドキュメントを漁っていましたが、これといったものが見つからず。。
あきらめかけていましたが、ゆくゆく考えると、バリデーションを行っている分類はPydanticの機能。
ということでPydantic(V2)の公式ドキュメントを見ていくとありました。
きちんと書いてありました。(以下コード抜粋)
from typing import Dict, List
from pydantic_core import ErrorDetails
from pydantic import BaseModel, HttpUrl, ValidationError
CUSTOM_MESSAGES = {
'int_parsing': 'This is not an integer! 🤦',
'url_scheme': 'Hey, use the right URL scheme! I wanted {expected_schemes}.',
}
def convert_errors(
e: ValidationError, custom_messages: Dict[str, str]
) -> List[ErrorDetails]:
new_errors: List[ErrorDetails] = []
for error in e.errors():
custom_message = custom_messages.get(error['type'])
if custom_message:
ctx = error.get('ctx')
error['msg'] = (
custom_message.format(**ctx) if ctx else custom_message
)
new_errors.append(error)
return new_errors
class Model(BaseModel):
a: int
b: HttpUrl
try:
Model(a='wrong', b='ftp://example.com')
except ValidationError as e:
errors = convert_errors(e, CUSTOM_MESSAGES)
print(errors)
"""
[
{
'type': 'int_parsing',
'loc': ('a',),
'msg': 'This is not an integer! 🤦',
'input': 'wrong',
'url': 'https://errors.pydantic.dev/2/v/int_parsing',
},
{
'type': 'url_scheme',
'loc': ('b',),
'msg': "Hey, use the right URL scheme! I wanted 'http' or 'https'.",
'input': 'ftp://example.com',
'ctx': {'expected_schemes': "'http' or 'https'"},
'url': 'https://errors.pydantic.dev/2/v/url_scheme',
},
]
"""
CUSTOM_MESSAGES
にエラータイプとカスタムエラーメッセージを定義し、
ユーザー定義関数の convert_errors()
でエラータイプをキーに置換している模様。
エラータイプの一覧もありました。
FastAPIでバリデーションエラーの例外ハンドラをカスタマイズ
あとはFastAPIでバリデーションエラーの例外ハンドラをオーバーライドしてカスタムすればよさそう。
実装例
本を新規登録するAPIを作成。
CreateBookSchema
でリクエストプロパティ title
、description
を定義。
title
は『必須』、description
は『10文字以下』というバリデーションを設定しました。
CUSTOM_MESSAGES
には日本語にしたバリデーションエラーメッセージを定義。
convert_errors()
関数でバリデーションエラーメッセージを置換します。
そして、@app.exception_handler(RequestValidationError)
でバリデーションエラー時の例外ハンドラをオーバーライド。
from fastapi import FastAPI, status
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from pydantic import BaseModel, Field, ValidationError
from pydantic_core import ErrorDetails
# カスタムエラーメッセージ
CUSTOM_MESSAGES = {
"string_type": "{input}は必須項目です。",
"string_too_long": "{input}は{max_length}文字以下で入力してください。",
}
def convert_errors(
e: ValidationError,
messages: dict[str, str],
) -> list[ErrorDetails]:
"""バリデーションエラーメッセージをカスタマイズ"""
new_errors: list[ErrorDetails] = []
for error in e.errors():
message = messages.get(error["type"])
if message:
ctx = error.get("ctx")
input = error.get("loc")
error["msg"] = (
message.format(input=input[1], **ctx)
if ctx
else message.format(input=input[1])
)
new_errors.append(error)
return new_errors
app = FastAPI()
# 例外ハンドラをオーバーライド
@app.exception_handler(RequestValidationError)
def validation_exception_handler(_, e: RequestValidationError):
# ここでエラーメッセージを日本語に置換
exc = convert_errors(e=e, messages=CUSTOM_MESSAGES)
return JSONResponse(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
content=jsonable_encoder({"detail": exc}),
)
class CreateBookSchema(BaseModel):
title: str
description: str = Field(max_length=10)
@app.post("/books")
def create_book(request: CreateBookSchema):
return {"data": request}
バリデーションエラーメッセージが日本語になりました!
Discussion