Skip to content

查詢參數與字串驗證

🌐 AI 與人類共同完成的翻譯

此翻譯由人類指導的 AI 完成。🤝

可能會有對原意的誤解,或讀起來不自然等問題。🤖

你可以透過協助我們更好地引導 AI LLM來改進此翻譯。

英文版

FastAPI 允許你為參數宣告額外的資訊與驗證。

以下面這個應用為例:

from fastapi import FastAPI

app = FastAPI()


@app.get("/items/")
async def read_items(q: str | None = None):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

查詢參數 q 的型別是 str | None,表示它是 str 但也可以是 None,而且預設值就是 None,因此 FastAPI 會知道它不是必填。

注意

FastAPI 會因為預設值是 = None 而知道 q 不是必填。

使用 str | None 也能讓你的編輯器提供更好的支援並偵測錯誤。

額外驗證

我們要強制:即使 q 是可選,只要提供了,長度就不能超過 50 個字元。

匯入 QueryAnnotated

要達成這點,先匯入:

  • fastapi 匯入 Query
  • typing 匯入 Annotated
from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(max_length=50)] = None):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: str | None = Query(default=None, max_length=50)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

說明

FastAPI 自 0.95.0 版起加入並開始推薦使用 Annotated

如果你的版本較舊,嘗試使用 Annotated 會出錯。

請先至少 升級 FastAPI 版本 到 0.95.1 再使用 Annotated

q 參數的型別中使用 Annotated

還記得先前在 Python 型別介紹 提到可以用 Annotated 為參數加入中繼資料嗎?

現在就用在 FastAPI 上吧。🚀

我們原本的型別註記是:

q: str | None = None

接著把它用 Annotated 包起來,變成:

q: Annotated[str | None] = None

這兩種寫法代表的意思相同:q 可以是 strNone,且預設是 None

現在來做有趣的部分。🎉

q 參數的 Annotated 中加入 Query

既然我們有可以放更多資訊的 Annotated(在此是額外驗證),就把 Query 放進 Annotated,並把參數 max_length 設為 50

from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(max_length=50)] = None):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: str | None = Query(default=None, max_length=50)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

注意預設值仍然是 None,所以這個參數仍是可選。

不過,現在在 Annotated 裡有 Query(max_length=50),我們就告訴 FastAPI 要對這個值做「額外驗證」,最多 50 個字元即可。😎

提示

這裡用的是 Query(),因為這是「查詢參數」。稍後你會看到 Path()Body()Header()Cookie() 等,它們也接受與 Query() 相同的參數。

FastAPI 現在會:

  • 驗證資料,確保長度最多 50 個字元
  • 當資料不合法時,回給用戶端清楚的錯誤
  • 在 OpenAPI 的路徑操作中文件化該參數(因此會出現在自動文件 UI)

替代方式(舊):將 Query 作為預設值

舊版 FastAPI(0.95.0 以前)需要把 Query 當成參數的預設值,而不是放在 Annotated 裡。你很可能會在各處看到這種寫法,所以我也會說明一下。

提示

新程式碼且在可能的情況下,請依上面說明使用 Annotated。它有多項優點(如下所述),而沒有缺點。🍰

這是把 Query() 作為函式參數預設值的寫法,並把參數 max_length 設為 50:

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: str | None = Query(default=None, max_length=50)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants
from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(max_length=50)] = None):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

在這種情況下(未使用 Annotated),我們必須用 Query() 取代函式中的預設值 None,因此需要用 Query(default=None) 來設定預設值;對 FastAPI 而言,這達到相同目的。

所以:

q: str | None = Query(default=None)

…會讓參數變為可選、預設值是 None,等同於:

q: str | None = None

但用 Query 的版本會明確宣告它是查詢參數。

接著,我們可以傳更多參數給 Query。此例中是用於字串的 max_length 參數:

q: str | None = Query(default=None, max_length=50)

這一樣會驗證資料、在資料不合法時顯示清楚錯誤,並在 OpenAPI 的路徑操作中文件化該參數。

Query 作為預設值或放在 Annotated

注意,把 Query 放在 Annotated 內時,不能使用 Querydefault 參數。

請改用函式參數的實際預設值。否則會不一致。

例如,這是不允許的:

q: Annotated[str, Query(default="rick")] = "morty"

…因為不清楚預設值到底該是 "rick" 還是 "morty"

因此,你可以(且更推薦)這樣寫:

q: Annotated[str, Query()] = "rick"

…或在較舊的程式碼中你會看到:

q: str = Query(default="rick")

Annotated 的優點

建議使用 Annotated,而不是在函式參數上使用(舊式的)預設值寫法,理由很多,且更好。🤓

函式參數的「預設值」就是「實際的預設值」,這在 Python 的直覺上更一致。😌

你也可以在沒有 FastAPI 的其他地方「直接呼叫」同一個函式,而且能「如預期」運作。若有「必填」參數(沒有預設值),你的「編輯器」會提示錯誤,「Python」在執行時也會抱怨你未傳遞必填參數。

若不使用 Annotated、改用「(舊式)預設值」寫法,你在沒有 FastAPI 的「其他地方」呼叫該函式時,就得「記得」傳入正確參數,否則值會和預期不同(例如會得到 QueryInfo 或類似的東西,而不是 str)。你的編輯器不會提示,Python 執行該函式時也不會抱怨,只有在內部操作失敗時才會出錯。

因為 Annotated 可以有多個中繼資料註解,你甚至可以用同一個函式配合其他工具,例如 Typer。🚀

加入更多驗證

你也可以加入 min_length 參數:

from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    q: Annotated[str | None, Query(min_length=3, max_length=50)] = None,
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: str | None = Query(default=None, min_length=3, max_length=50)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

加入正規表示式

你可以定義參數必須符合的 regular expression pattern

from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    q: Annotated[
        str | None, Query(min_length=3, max_length=50, pattern="^fixedquery$")
    ] = None,
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    q: str | None = Query(
        default=None, min_length=3, max_length=50, pattern="^fixedquery$"
    ),
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

這個特定的正規表示式樣式會檢查收到的參數值是否:

  • ^:以後續的字元開頭,前面不能有其他字元。
  • fixedquery:必須正好等於 fixedquery
  • $:在此結束,fixedquery 後面不能再有其他字元。

如果你對「正規表示式」感到困惑,別擔心。這對很多人來說都不容易。你仍然可以先不使用正規表示式就完成很多事情。

現在你知道,當你需要它們時,可以在 FastAPI 中使用它們。

預設值

當然,你可以使用 None 以外的預設值。

假設你想宣告查詢參數 qmin_length3,且預設值是 "fixedquery"

from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: Annotated[str, Query(min_length=3)] = "fixedquery"):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: str = Query(default="fixedquery", min_length=3)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

注意

只要有任何型別的預設值(包含 None),參數就是可選(非必填)。

必填參數

當我們不需要宣告更多的驗證或中繼資料時,只要不提供預設值,就能讓查詢參數 q 成為必填,例如:

q: str

而不是:

q: str | None = None

但現在我們要搭配 Query 來宣告,例如:

q: Annotated[str | None, Query(min_length=3)] = None

因此,在使用 Query 時若要宣告值為必填,只要不要宣告預設值即可:

from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: Annotated[str, Query(min_length=3)]):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: str = Query(min_length=3)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

必填,但可為 None

你可以宣告參數可以接受 None,但仍然是必填。這會強制用戶端一定要送出一個值,即使該值是 None

要做到這點,你可以宣告 None 是合法型別,但不要宣告預設值:

from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(min_length=3)]):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: str | None = Query(min_length=3)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

查詢參數清單/多個值

當你用 Query 明確定義查詢參數時,也可以讓它接收一個值的清單;換句話說,就是「多個值」。

例如,要宣告查詢參數 q 可以在 URL 中出現多次,你可以這樣寫:

from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: Annotated[list[str] | None, Query()] = None):
    query_items = {"q": q}
    return query_items
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: list[str] | None = Query(default=None)):
    query_items = {"q": q}
    return query_items

若使用這樣的 URL:

http://localhost:8000/items/?q=foo&q=bar

你會在路徑操作函式的參數 q 中,收到多個 q 查詢參數的值(foobar),以 Python 的 list 形式。

因此,對該 URL 的回應會是:

{
  "q": [
    "foo",
    "bar"
  ]
}

提示

要宣告型別為 list 的查詢參數(如上例),需要明確使用 Query,否則它會被解讀為請求本文。

互動式 API 文件也會相應更新,以便支援多個值:

查詢參數清單/多個值的預設值

也可以在未提供任何值時,定義 list 型別的預設值:

from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: Annotated[list[str], Query()] = ["foo", "bar"]):
    query_items = {"q": q}
    return query_items
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: list[str] = Query(default=["foo", "bar"])):
    query_items = {"q": q}
    return query_items

如果你前往:

http://localhost:8000/items/

q 的預設值會是:["foo", "bar"],而回應會是:

{
  "q": [
    "foo",
    "bar"
  ]
}

只使用 list

你也可以直接使用 list,而不是 list[str]

from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: Annotated[list, Query()] = []):
    query_items = {"q": q}
    return query_items
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: list = Query(default=[])):
    query_items = {"q": q}
    return query_items

注意

注意,在這種情況下,FastAPI 不會檢查清單的內容。

例如,list[int] 會檢查(並文件化)清單內容為整數;但單獨使用 list 則不會。

宣告更多中繼資料

你可以為參數加入更多資訊。

這些資訊會被包含在產生的 OpenAPI 中,供文件 UI 與外部工具使用。

注意

請留意,不同工具對 OpenAPI 的支援程度可能不同。

有些工具可能暫時還不會顯示所有額外資訊;不過多半這些缺漏功能已在開發規劃中。

你可以加入 title

from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    q: Annotated[str | None, Query(title="Query string", min_length=3)] = None,
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    q: str | None = Query(default=None, title="Query string", min_length=3),
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

以及 description

from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    q: Annotated[
        str | None,
        Query(
            title="Query string",
            description="Query string for the items to search in the database that have a good match",
            min_length=3,
        ),
    ] = None,
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    q: str | None = Query(
        default=None,
        title="Query string",
        description="Query string for the items to search in the database that have a good match",
        min_length=3,
    ),
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

別名參數

想像你希望參數名稱是 item-query

像這樣:

http://127.0.0.1:8000/items/?item-query=foobaritems

item-query 不是合法的 Python 變數名稱。

最接近的大概是 item_query

但你仍然需要它就是 item-query...

那你可以宣告一個 alias,實際上就會用這個別名來讀取參數值:

from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: Annotated[str | None, Query(alias="item-query")] = None):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(q: str | None = Query(default=None, alias="item-query")):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

棄用參數

現在假設你不再喜歡這個參數了。

你必須暫時保留它,因為還有用戶端在用,但你希望文件能清楚標示它是已棄用

接著把參數 deprecated=True 傳給 Query

from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    q: Annotated[
        str | None,
        Query(
            alias="item-query",
            title="Query string",
            description="Query string for the items to search in the database that have a good match",
            min_length=3,
            max_length=50,
            pattern="^fixedquery$",
            deprecated=True,
        ),
    ] = None,
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    q: str | None = Query(
        default=None,
        alias="item-query",
        title="Query string",
        description="Query string for the items to search in the database that have a good match",
        min_length=3,
        max_length=50,
        pattern="^fixedquery$",
        deprecated=True,
    ),
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

文件會這樣顯示:

從 OpenAPI 排除參數

若要把某個查詢參數從產生的 OpenAPI(以及自動文件系統)中排除,將 Queryinclude_in_schema 設為 False

from typing import Annotated

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    hidden_query: Annotated[str | None, Query(include_in_schema=False)] = None,
):
    if hidden_query:
        return {"hidden_query": hidden_query}
    else:
        return {"hidden_query": "Not found"}
🤓 Other versions and variants

Tip

Prefer to use the Annotated version if possible.

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    hidden_query: str | None = Query(default=None, include_in_schema=False),
):
    if hidden_query:
        return {"hidden_query": hidden_query}
    else:
        return {"hidden_query": "Not found"}

自訂驗證

有時你需要做一些上述參數無法處理的「自訂驗證」。

這種情況下,你可以使用「自訂驗證函式」,它會在一般驗證之後套用(例如先確認值是 str 之後)。

你可以在 Annotated 中使用 Pydantic 的 AfterValidator 來達成。

提示

Pydantic 也有 BeforeValidator 等等。🤓

例如,以下自訂驗證器會檢查項目 ID 是否以 isbn- 開頭(ISBN 書籍編號),或以 imdb- 開頭(IMDB 電影 URL 的 ID):

import random
from typing import Annotated

from fastapi import FastAPI
from pydantic import AfterValidator

app = FastAPI()

data = {
    "isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
    "imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
    "isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
}


def check_valid_id(id: str):
    if not id.startswith(("isbn-", "imdb-")):
        raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
    return id


@app.get("/items/")
async def read_items(
    id: Annotated[str | None, AfterValidator(check_valid_id)] = None,
):
    if id:
        item = data.get(id)
    else:
        id, item = random.choice(list(data.items()))
    return {"id": id, "name": item}

說明

這需搭配 Pydantic 2 或以上版本。😎

提示

如果你需要做任何需要與「外部元件」溝通的驗證(例如資料庫或其他 API),應該改用「FastAPI 依賴」(FastAPI Dependencies),你稍後會學到。

這些自訂驗證器適用於只需使用請求中「同一份資料」即可完成的檢查。

理解這段程式碼

重點就是在 Annotated 中使用「AfterValidator 搭配函式」。如果你願意,可以略過這一節。🤸


但如果你對這個範例感到好奇且仍有興致,以下是一些額外細節。

使用 value.startswith() 的字串

你注意到了嗎?字串的 value.startswith() 可以接收一個 tuple,並逐一檢查 tuple 中的每個值:

# Code above omitted 👆

def check_valid_id(id: str):
    if not id.startswith(("isbn-", "imdb-")):
        raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
    return id

# Code below omitted 👇
👀 Full file preview
import random
from typing import Annotated

from fastapi import FastAPI
from pydantic import AfterValidator

app = FastAPI()

data = {
    "isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
    "imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
    "isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
}


def check_valid_id(id: str):
    if not id.startswith(("isbn-", "imdb-")):
        raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
    return id


@app.get("/items/")
async def read_items(
    id: Annotated[str | None, AfterValidator(check_valid_id)] = None,
):
    if id:
        item = data.get(id)
    else:
        id, item = random.choice(list(data.items()))
    return {"id": id, "name": item}

隨機項目

透過 data.items() 我們會得到一個包含每個字典項目鍵值對 tuple 的 iterable object

我們用 list(data.items()) 把這個可疊代物件轉成正式的 list

接著用 random.choice() 從清單中取得一個「隨機值」,也就是一個 (id, name) 的 tuple。可能像是 ("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")

然後把這個 tuple 的兩個值分別指定給變數 idname

因此,即使使用者沒有提供 item ID,仍然會收到一個隨機建議。

……而這全部只用一行簡單的程式碼完成。🤯 你不愛 Python 嗎?🐍

# Code above omitted 👆

@app.get("/items/")
async def read_items(
    id: Annotated[str | None, AfterValidator(check_valid_id)] = None,
):
    if id:
        item = data.get(id)
    else:
        id, item = random.choice(list(data.items()))
    return {"id": id, "name": item}
👀 Full file preview
import random
from typing import Annotated

from fastapi import FastAPI
from pydantic import AfterValidator

app = FastAPI()

data = {
    "isbn-9781529046137": "The Hitchhiker's Guide to the Galaxy",
    "imdb-tt0371724": "The Hitchhiker's Guide to the Galaxy",
    "isbn-9781439512982": "Isaac Asimov: The Complete Stories, Vol. 2",
}


def check_valid_id(id: str):
    if not id.startswith(("isbn-", "imdb-")):
        raise ValueError('Invalid ID format, it must start with "isbn-" or "imdb-"')
    return id


@app.get("/items/")
async def read_items(
    id: Annotated[str | None, AfterValidator(check_valid_id)] = None,
):
    if id:
        item = data.get(id)
    else:
        id, item = random.choice(list(data.items()))
    return {"id": id, "name": item}

重點回顧

你可以為參數宣告額外的驗證與中繼資料。

通用的驗證與中繼資料:

  • alias
  • title
  • description
  • deprecated

字串專用的驗證:

  • min_length
  • max_length
  • pattern

使用 AfterValidator 的自訂驗證。

在這些範例中,你看到了如何為 str 值宣告驗證。

接下來的章節會示範如何為其他型別(像是數字)宣告驗證。