FastAPI教程 查詢參數(shù)和字符串校驗(yàn)

2021-11-02 14:58 更新

FastAPI 允許你為參數(shù)聲明額外的信息和校驗(yàn)。

讓我們以下面的應(yīng)用程序?yàn)槔?/p>

from typing import Optional

from fastapi import FastAPI

app = FastAPI()


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

查詢參數(shù) q 的類型為 str,默認(rèn)值為 None,因此它是可選的。

額外的校驗(yàn)

我們打算添加約束條件:即使 q 是可選的,但只要提供了該參數(shù),則該參數(shù)值不能超過(guò)50個(gè)字符的長(zhǎng)度。

導(dǎo)入 Query

為此,首先從 fastapi 導(dǎo)入 Query:

from typing import Optional

from fastapi import FastAPI, Query

app = FastAPI()


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

使用 Query 作為默認(rèn)值

現(xiàn)在,將 Query 用作查詢參數(shù)的默認(rèn)值,并將它的 max_length 參數(shù)設(shè)置為 50:

from typing import Optional

from fastapi import FastAPI, Query

app = FastAPI()


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

由于我們必須用 Query(None) 替換默認(rèn)值 None,Query 的第一個(gè)參數(shù)同樣也是用于定義默認(rèn)值。

所以:

q: str = Query(None)

...使得參數(shù)可選,等同于:

q: str = None

但是 Query 顯式地將其聲明為查詢參數(shù)。

然后,我們可以將更多的參數(shù)傳遞給 Query。在本例中,適用于字符串的 max_length 參數(shù):

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

將會(huì)校驗(yàn)數(shù)據(jù),在數(shù)據(jù)無(wú)效時(shí)展示清晰的錯(cuò)誤信息,并在 OpenAPI 模式的路徑操作中記錄該參??數(shù)。

添加更多校驗(yàn)

你還可以添加 min_length 參數(shù):

from typing import Optional

from fastapi import FastAPI, Query

app = FastAPI()


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

添加正則表達(dá)式

你可以定義一個(gè)參數(shù)值必須匹配的正則表達(dá)式:

from typing import Optional

from fastapi import FastAPI, Query

app = FastAPI()


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

這個(gè)指定的正則表達(dá)式通過(guò)以下規(guī)則檢查接收到的參數(shù)值:

  • ^:以該符號(hào)之后的字符開(kāi)頭,符號(hào)之前沒(méi)有字符。
  • fixedquery: 值精確地等于 fixedquery。
  • $: 到此結(jié)束,在 fixedquery 之后沒(méi)有更多字符。

如果你對(duì)所有的這些「正則表達(dá)式」概念感到迷茫,請(qǐng)不要擔(dān)心。對(duì)于許多人來(lái)說(shuō)這都是一個(gè)困難的主題。你仍然可以在無(wú)需正則表達(dá)式的情況下做很多事情。

但是,一旦你需要用到并去學(xué)習(xí)它們時(shí),請(qǐng)了解你已經(jīng)可以在 FastAPI 中直接使用它們。

默認(rèn)值

你可以向 Query 的第一個(gè)參數(shù)傳入 None 用作查詢參數(shù)的默認(rèn)值,以同樣的方式你也可以傳遞其他默認(rèn)值。

假設(shè)你想要聲明查詢參數(shù) q,使其 min_length 為 3,并且默認(rèn)值為 fixedquery:

from fastapi import FastAPI, Query

app = FastAPI()


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

Note

具有默認(rèn)值還會(huì)使該參數(shù)成為可選參數(shù)。

聲明為必需參數(shù)

當(dāng)我們不需要聲明額外的校驗(yàn)或元數(shù)據(jù)時(shí),只需不聲明默認(rèn)值就可以使 q 參數(shù)成為必需參數(shù),例如:

q: str

代替:

q: str = None

但是現(xiàn)在我們正在用 Query 聲明它,例如:

q: str = Query(None, min_length=3)

因此,當(dāng)你在使用 Query 且需要聲明一個(gè)值是必需的時(shí),可以將 ... 用作第一個(gè)參數(shù)值:

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

Info

如果你之前沒(méi)見(jiàn)過(guò) ... 這種用法:它是一個(gè)特殊的單獨(dú)值,它是 Python 的一部分并且被稱為「省略號(hào)」。

這將使 FastAPI 知道此查詢參數(shù)是必需的。

查詢參數(shù)列表 / 多個(gè)值

當(dāng)你使用 Query 顯式地定義查詢參數(shù)時(shí),你還可以聲明它去接收一組值,或換句話來(lái)說(shuō),接收多個(gè)值。

例如,要聲明一個(gè)可在 URL 中出現(xiàn)多次的查詢參數(shù) q,你可以這樣寫(xiě):

from typing import List, Optional

from fastapi import FastAPI, Query

app = FastAPI()


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

然后,輸入如下網(wǎng)址:

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

你會(huì)在路徑操作函數(shù)的函數(shù)參數(shù) q 中以一個(gè) Python list 的形式接收到查詢參數(shù) q 的多個(gè)值(foo 和 bar)。

因此,該 URL 的響應(yīng)將會(huì)是:

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

Tip

要聲明類型為 list 的查詢參數(shù),如上例所示,你需要顯式地使用 Query,否則該參數(shù)將被解釋為請(qǐng)求體。

交互式 API 文檔將會(huì)相應(yīng)地進(jìn)行更新,以允許使用多個(gè)值:

具有默認(rèn)值的查詢參數(shù)列表 / 多個(gè)值

你還可以定義在沒(méi)有任何給定值時(shí)的默認(rèn) list 值:

from typing import List

from fastapi import FastAPI, Query

app = FastAPI()


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

如果你訪問(wèn):

http://localhost:8000/items/

q 的默認(rèn)值將為:["foo", "bar"],你的響應(yīng)會(huì)是:

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

使用 list

你也可以直接使用 list 代替 List [str]:

from fastapi import FastAPI, Query

app = FastAPI()


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

Note

請(qǐng)記住,在這種情況下 FastAPI 將不會(huì)檢查列表的內(nèi)容。

例如,List[int] 將檢查(并記錄到文檔)列表的內(nèi)容必須是整數(shù)。但是單獨(dú)的 list 不會(huì)。

聲明更多元數(shù)據(jù)

你可以添加更多有關(guān)該參數(shù)的信息。

這些信息將包含在生成的 OpenAPI 模式中,并由文檔用戶界面和外部工具所使用。

Note

請(qǐng)記住,不同的工具對(duì) OpenAPI 的支持程度可能不同。

其中一些可能不會(huì)展示所有已聲明的額外信息,盡管在大多數(shù)情況下,缺少的這部分功能已經(jīng)計(jì)劃進(jìn)行開(kāi)發(fā)。

你可以添加 title:

from typing import Optional

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    q: Optional[str] = Query(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 Optional

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    q: Optional[str] = Query(
        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

別名參數(shù)

假設(shè)你想要查詢參數(shù)為 item-query。

像下面這樣:

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

但是 item-query 不是一個(gè)有效的 Python 變量名稱。

最接近的有效名稱是 item_query。

但是你仍然要求它在 URL 中必須是 item-query...

這時(shí)你可以用 alias 參數(shù)聲明一個(gè)別名,該別名將用于在 URL 中查找查詢參數(shù)值:

from typing import Optional

from fastapi import FastAPI, Query

app = FastAPI()


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

棄用參數(shù)

現(xiàn)在假設(shè)你不再喜歡此參數(shù)。

你不得不將其保留一段時(shí)間,因?yàn)橛行┛蛻舳苏谑褂盟?,但你希望文檔清楚地將其展示為已棄用。

那么將參數(shù) deprecated=True 傳入 Query:

from typing import Optional

from fastapi import FastAPI, Query

app = FastAPI()


@app.get("/items/")
async def read_items(
    q: Optional[str] = Query(
        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,
        regex="^fixedquery$",
        deprecated=True,
    )
):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

文檔將會(huì)像下面這樣展示它:

總結(jié)

你可以為查詢參數(shù)聲明額外的校驗(yàn)和元數(shù)據(jù)。

通用的校驗(yàn)和元數(shù)據(jù):

  • alias
  • title
  • description
  • deprecated

特定于字符串的校驗(yàn):

  • min_length
  • max_length
  • regex

在這些示例中,你了解了如何聲明對(duì) str 值的校驗(yàn)。

請(qǐng)參閱下一章節(jié),以了解如何聲明對(duì)其他類型例如數(shù)值的校驗(yàn)。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)