2022年10月21日金曜日

FastAPIでPOSTリクエストのボディをバリデーションする方法

FastAPIでPOSTリクエストのボディをバリデーションする方法

概要

前回 FastAPIに入門しました

今回はリクエストのバリデーションを実装する方法を紹介します

環境

  • macOS 11.6.8
  • Python 3.10.2
  • FastAPI 0.83.0

pydandic の @validator を使う

おそらく一番メジャーでかつ簡単なのが pydantic の validator デコレータを使う方法だと思います
FastAPI は pydantic と密接に関係しており主にリクエストのモデルを扱う場合に使用する場合が多いです
なのでバリデーションも pydantic の機能を使うのが良いと思います

from pydantic import BaseModel, BaseSettings, validator
from fastapi import FastAPI

app = FastAPI()


class Settings(BaseSettings):
    message: str = ""


settings = Settings()


class Item(BaseModel):
    message: str

    @validator('message')
    def check_max_length(cls, v, values, **kwargs):
        if len(v) > 10:
            raise ValueError('Must be 10 characters or less.')
        return v

    @validator('message')
    def contain_exclamation(cls, v, values, **kwargs):
        if '!' not in v:
            raise ValueError('Must contain a exclamation mark')
        return v

@app.get("/")
async def get_msg():
    return {"message": settings.message}


@app.post("/")
def set_msg(item: Item):
    settings.message = item.message
    return {"message": item.message}

解説

@validator('message') がポイントです
BaseModel を継承したリクエストモデル用のクラスに実装します
引数の値はバリデーションを行うフィールドの値を指定します
同じフィールドい対してバリデーションのメソッドはいくつも登録することができるのでバリデーションの種類に応じてわけると良いかなと思います

ただバリデーションルールはOpenAPIに反映されない

これで /openapi.json を見るとわかるのですがバリデーション情報は openapi.json には反映されていません

Body を使う

pydantic を使わずにリクエストボディを定義することもできます (pydantic と組み合わせることもできます)
Body を使って定義することで openapi にもバリデーション情報が反映されます

from pydantic import BaseSettings
from fastapi import FastAPI, Body

app = FastAPI()


class Settings(BaseSettings):
    message: str = ""


settings = Settings()


@app.get("/")
async def get_msg():
    return settings.message


@app.post("/")
def set_msg(message: dict[str, str] = Body(max_length=10, regex=".*!.*", example={"message": "Hello!"})):
    settings.message = message
    return message

Body の他に指定可能なパラメータは参考サイトのURLを参照してください

動作確認

  • pipenv run uvicorn app:app --reload

で起動します

  • curl -XPOST localhost:8000 -H 'content-type: application/json' -d '{"message":"hoge!"}'

は成功します

  • curl -XPOST localhost:8000 -H 'content-type: application/json' -d '{"message":"hoge"}'
  • curl -XPOST localhost:8000 -H 'content-type: application/json' -d '{"message":"hogehogehoge!"}'

はエラーになることが確認できると思います

参考サイト

0 件のコメント:

コメントを投稿