基礎から学ぶPython入門 90日コース | データベース・Web API - Day 69:POST API

Python 90日で身につけるPython
スポンサーリンク
スポンサーリンク

Day 69:POST API ― 「外から送られてきたデータを、ちゃんと受け止める」

Day 69では、FastAPI入門の続きとして、 POST API をテーマに進めていきます。

キーワードはこの4つです。

  • POST API
  • リクエストボディ
  • データモデル
  • バリデーション

昨日のDay 68では、GET APIを通して「情報を返す」側を体験しました。 今日はその逆、「クライアントから送られてくるデータを受け取り、処理する」 側に回ります。

ここを理解できると、 「フォームから送信されたデータを保存する」「外部サービスからJSONを受け取る」 といった、現実のWeb/API開発にぐっと近づいていきます。

POST APIとは ― 「データを送ってもらうための入り口」

GETとPOSTの役割の違いを整理する

まずは、HTTPメソッドの役割をざっくり整理しておきます。

  • GET:情報を取得する(読む)
  • POST:新しい情報を送る(作る・登録する)

もちろん、POSTは「作る」だけでなく、 「検索条件を送る」「処理の指示を送る」などにも使われますが、 基本的には 「何かを送る」ためのメソッド と考えておくと分かりやすいです。

FastAPIでのPOST APIの基本形

FastAPIでは、 @app.post("/path") というデコレータで、POST APIを定義します。

from fastapi import FastAPI

app = FastAPI()


@app.post("/echo")
def echo():
    """
    とてもシンプルなPOST APIの例です。
    まだリクエストボディは扱っていません。
    """
    return {"message": "POSTでアクセスされました。"}
Python

ただ、これだけだと「POSTされたこと」しか分かりません。 本番のAPIでは、リクエストボディ(送られてきたJSONなど) を受け取って処理することがほとんどです。

リクエストボディとは ― 「APIに渡される中身のデータ」

リクエストボディのイメージ

リクエストボディ とは、

クライアント(ブラウザや他のサービス)が、 APIに対して送ってくる「中身のデータ」のこと

です。

例えば、ユーザー登録APIを考えてみましょう。

{
  "name": "Taro",
  "email": "taro@example.com",
  "age": 25
}
JSON

こういったJSONが、HTTPリクエストの「ボディ部分」に入って送られてきます。 POST APIは、このボディを受け取って、 「データベースに保存する」「バリデーションする」「レスポンスを返す」 といった処理を行います。

FastAPIでリクエストボディを受け取る基本形

FastAPIでは、 関数の引数に「データモデル」を指定することで、リクエストボディを受け取ります。

ここで登場するのが Pydanticモデル です。

データモデル(Pydantic) ― 「JSONの形をPythonで表現する」

Pydanticモデルとは

FastAPIは内部で Pydantic というライブラリを使っていて、 これを使うことで、

  • リクエストボディのJSONを、Pythonのオブジェクトとして扱える
  • 型ヒントに基づいて、自動でバリデーションしてくれる
  • ドキュメント(OpenAPI)にも反映してくれる

という、かなり嬉しいことが起こります。

まずは、Pydanticモデルを定義してみましょう。

# day69_post_api.py
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class UserCreate(BaseModel):
    """
    ユーザー作成用のリクエストボディを表すデータモデルです。
    クライアントから送られてくるJSONの形を、このクラスで定義します。
    """

    name: str
    email: str
    age: int | None = None  # 年齢は任意項目とします
Python

ここでやっていることは、

  • BaseModel を継承した UserCreate クラスを作る
  • name, email, age という属性を定義する
  • 型ヒント(str, int | None)で、データの型を指定する
  • デフォルト値 None を指定することで、「任意項目」にできる

という、まさに「JSONの形をPythonで表現する」作業です。

POST APIでデータモデルを受け取る ― 「JSONがそのままPythonオブジェクトになる」

ユーザー作成APIの例

この UserCreate モデルを使って、 実際にPOST APIを作ってみます。

@app.post("/users")
def create_user(user: UserCreate):
    """
    ユーザー作成用のPOST APIです。
    リクエストボディのJSONを UserCreate モデルとして受け取ります。

    例として、送られてきた内容をそのままレスポンスとして返します。
    本来はここでDB保存などを行います。
    """

    # user は UserCreate のインスタンスです。
    # user.name, user.email, user.age で各値にアクセスできます。
    print(f"[POST] 新しいユーザー: name={user.name}, email={user.email}, age={user.age}")

    # ここでは、簡単なメッセージと一緒に返してみます。
    return {
        "message": "ユーザーを受け取りました。",
        "user": user,  # PydanticモデルはそのままJSONに変換されます。
    }
Python

ここでのポイントは、

  • 関数の引数 user: UserCreate が、リクエストボディを受け取る役割を持つ
  • クライアントから送られてきたJSONが、自動的に UserCreate インスタンスに変換される
  • user.nameuser.email のように、Pythonのオブジェクトとして扱える
  • 戻り値に user を含めると、Pydanticが自動でJSONに変換してくれる

というところです。

実際のリクエスト例(イメージ)

例えば、次のようなJSONをPOSTするとします。

{
  "name": "Taro",
  "email": "taro@example.com",
  "age": 25
}
JSON

このとき、FastAPIは、

  1. JSONを受け取る
  2. UserCreate の定義に基づいて、型チェック・バリデーションを行う
  3. 問題なければ user: UserCreate に変換して関数に渡す

という流れで処理してくれます。

バリデーション ― 「おかしなデータを、入口でちゃんと止める」

型ヒントによる基本的なバリデーション

Pydanticモデルに型ヒントを書いておくと、 FastAPIは自動的にバリデーションを行ってくれます。

例えば、

  • name: str に対して、数値が送られてきたらエラー
  • age: int | None に対して、文字列が送られてきたらエラー

という具合です。

この「型に合わないデータは受け付けない」という仕組みが、 APIの安全性と信頼性をぐっと高めてくれます。

もう少し踏み込んだバリデーション(長さ・形式など)

Pydanticは、もう少し細かいバリデーションも書けます。

例えば、「メールアドレスの形式をチェックしたい」という場合。

from pydantic import BaseModel, EmailStr


class UserCreate(BaseModel):
    """
    メールアドレスの形式チェックを含んだユーザーモデルの例です。
    EmailStr 型を使うことで、メール形式のバリデーションが自動で行われます。
    """

    name: str
    email: EmailStr  # メールアドレス形式をチェックしてくれる型
    age: int | None = None
Python

EmailStr を使うと、

  • taro@example.com → OK
  • not-an-email → バリデーションエラー

というように、形式チェックを自動で行ってくれます。

バリデーションエラーが起きたとき

もし、バリデーションに失敗した場合、 FastAPIは自動的に 400 Bad Request とともに、 「どの項目がどうおかしいのか」をJSONで返してくれます。

これは、APIを使う側にとってもとても親切で、 「何が間違っているのか」をすぐに理解できるようになります。

Day 69ミニテンプレート ― POST+モデル+バリデーションの基本セット

最後に、今日の内容をひとまとめにした POST API入門テンプレート を載せておきます。

# day69_post_api_template.py
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr

app = FastAPI()


class UserCreate(BaseModel):
    """
    ユーザー作成用のリクエストボディモデルです。
    name: 必須の文字列
    email: メールアドレス形式の必須文字列
    age: 任意の整数
    """

    name: str
    email: EmailStr
    age: int | None = None


@app.get("/")
def read_root():
    """
    簡単なウェルカムメッセージを返すGET APIです。
    """
    return {"message": "Day 69: POST API 入門へようこそ"}


@app.post("/users")
def create_user(user: UserCreate):
    """
    ユーザー作成用のPOST APIです。
    リクエストボディのJSONを UserCreate として受け取り、
    バリデーション済みのデータとして扱います。
    """

    # user はバリデーション済みの UserCreate インスタンスです。
    print(f"[POST] 新規ユーザー: name={user.name}, email={user.email}, age={user.age}")

    # 本来はここでDB保存などを行いますが、今回は受け取った内容をそのまま返します。
    return {
        "message": "ユーザーを登録しました(仮)。",
        "user": user,
    }
Python

このファイルを保存して、

bash

uvicorn day69_post_api_template:app --reload

と実行すれば、

  • GET / でウェルカムメッセージ
  • POST /users で、UserCreate に基づいたリクエストボディの受け取り&バリデーション

を試すことができます。

Day 69のまとめ ― 「APIの入口で、データをちゃんと“選別”できるようになる」

今日の主役は、

  • POST API:クライアントからデータを送ってもらうための入り口
  • リクエストボディ:JSONなどの「中身のデータ」
  • データモデル(Pydantic):リクエストボディの形をPythonで表現するクラス
  • バリデーション:おかしなデータを入口で止める仕組み

でした。

FastAPIとPydanticを組み合わせることで、

  • 「どんな形のデータを受け付けるか」を、コードとして明確にできる
  • 型ヒントに基づいて、自動でバリデーションしてくれる
  • エラー時のレスポンスも、分かりやすいJSONで返してくれる

という、かなり心強い環境が整います。

APIは「誰かからデータを受け取る窓口」でもあり、 その窓口で 「何でもかんでも受け入れる」のではなく、 「ちゃんとしたデータだけを通す」 ことが、とても大切です。

Day 69で学んだPOST+モデル+バリデーションの組み合わせは、 そのための、静かだけれど強力な“フィルター”になってくれます。

タイトルとURLをコピーしました