FastAPI Request 表單資料 (Form Data)

除了 JSON (application/json) 之外,Web 開發中另一個常見的資料傳輸格式是 Form Data (表單資料),即 application/x-www-form-urlencoded。這通常用在 HTML 表單提交,或是簡單的登入 API。

安裝 python-multipart

要處理 Form Data (以及 File Upload),你需要先安裝 python-multipart 套件,因為 FastAPI 核心並不包含它。

pip install python-multipart

使用 Form

Form Data 的使用方式與 Body, Query, Path 非常像。你只需要從 fastapi 導入 Form

from typing import Annotated
from fastapi import FastAPI, Form

app = FastAPI()

@app.post("/login/")
async def login(
    username: Annotated[str, Form()],
    password: Annotated[str, Form()]
):
    return {"username": username}

在這個例子中:

  • Request Method: POST
  • Content-Type: application/x-www-form-urlencoded
  • Body: username=myname&password=mypassword

如果你使用 BodyPydantic Model,FastAPI 會預期是 JSON;但如果你使用 Form,FastAPI 就會告訴 Swagger UI 以 Form Data 的方式發送請求。

Form 參數的設定

Form 支援所有 Body, Query, Path 支援的參數驗證:

  • default: 預設值
  • ...: 必填
  • min_length, max_length, regex 等字串驗證
  • title, description 等文件描述
@app.post("/request-form/")
async def handle_form(
    username: str = Form(..., min_length=3),
    password: str = Form(..., description="User's password"),
    agree_tos: bool = Form(False)
):
    return {"message": "Received"}

JSON 與 Form Data 混用?

注意: 根據 HTTP 標準,你通常不能在同一個請求中同時使用 JSON Body 和 Form Data。因為 Content-Type 只能有一個 (雖然 multipart/form-data 可以包含 JSON 欄位,但那是另一回事,我們會在檔案上傳章節提到)。

所以,如果你定義了 Pydantic Model (JSON) 又定義了 Form 參數,FastAPI 會報錯,因為它不知道該期待哪種 Content-Type。

總結

  • 安裝 python-multipart
  • 使用 Form(...) 來宣告表單欄位。
  • 常見於傳統 HTML 表單提交或 OAuth2 Password Flow 登入。