From 52fd45d05147fa433147eb405330a87f0f70a6ff Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Jul 2026 13:22:04 +0000 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=90=20Update=20translations=20for=20zh?= =?UTF-8?q?-hant=20(update-outdated)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/zh-hant/docs/advanced/dataclasses.md | 6 +- .../zh-hant/docs/advanced/generate-clients.md | 18 +-- .../docs/advanced/json-base64-bytes.md | 8 +- .../docs/advanced/openapi-callbacks.md | 6 +- .../zh-hant/docs/advanced/response-cookies.md | 10 +- .../zh-hant/docs/advanced/response-headers.md | 6 +- .../docs/advanced/security/oauth2-scopes.md | 76 +++++------ docs/zh-hant/docs/advanced/settings.md | 6 +- docs/zh-hant/docs/advanced/stream-data.md | 10 +- docs/zh-hant/docs/deployment/cloud.md | 2 +- docs/zh-hant/docs/deployment/docker.md | 6 +- docs/zh-hant/docs/deployment/manually.md | 12 +- .../docs/how-to/configure-swagger-ui.md | 4 +- .../docs/how-to/custom-request-and-route.md | 2 +- docs/zh-hant/docs/how-to/graphql.md | 20 +-- ...migrate-from-pydantic-v1-to-pydantic-v2.md | 20 ++- .../docs/how-to/separate-openapi-schemas.md | 36 +++--- .../docs/tutorial/bigger-applications.md | 2 +- docs/zh-hant/docs/tutorial/body.md | 2 + .../dependencies/dependencies-with-yield.md | 1 + docs/zh-hant/docs/tutorial/extra-models.md | 14 +- docs/zh-hant/docs/tutorial/first-steps.md | 30 ++--- docs/zh-hant/docs/tutorial/handling-errors.md | 4 +- docs/zh-hant/docs/tutorial/index.md | 2 +- docs/zh-hant/docs/tutorial/metadata.md | 12 +- .../tutorial/query-params-str-validations.md | 85 ++++++------ docs/zh-hant/docs/tutorial/query-params.md | 5 +- .../docs/tutorial/schema-extra-example.md | 4 +- .../docs/tutorial/security/first-steps.md | 44 +++---- .../tutorial/security/get-current-user.md | 2 +- .../docs/tutorial/security/oauth2-jwt.md | 4 +- .../docs/tutorial/security/simple-oauth2.md | 4 +- docs/zh-hant/docs/tutorial/sql-databases.md | 122 +++++++++--------- docs/zh-hant/docs/tutorial/static-files.md | 8 ++ docs/zh-hant/docs/tutorial/testing.md | 12 +- 35 files changed, 311 insertions(+), 294 deletions(-) diff --git a/docs/zh-hant/docs/advanced/dataclasses.md b/docs/zh-hant/docs/advanced/dataclasses.md index 0a673889e..64ba7dde2 100644 --- a/docs/zh-hant/docs/advanced/dataclasses.md +++ b/docs/zh-hant/docs/advanced/dataclasses.md @@ -63,12 +63,12 @@ FastAPI 建立在 **Pydantic** 之上,我之前示範過如何使用 Pydantic 7. 這裡 `response_model` 使用的是「`Author` dataclass 的清單」這種型別註記。 同樣地,你可以把 `dataclasses` 與標準型別註記組合使用。 -8. 注意這個「路徑操作函式」使用的是一般的 `def` 而非 `async def`。 +8. 注意這個*路徑操作函式*使用的是一般的 `def` 而非 `async def`。 一如往常,在 FastAPI 中你可以視需要混用 `def` 與 `async def`。 - 如果需要複習何時用哪個,請參考文件中關於 [`async` 與 `await`](../async.md#in-a-hurry) 的章節「In a hurry?」。 -9. 這個「路徑操作函式」回傳的不是 dataclass(雖然也可以),而是一個包含內部資料的字典清單。 + 如果需要複習何時用哪個,請參考文件中關於 [`async` 與 `await`](../async.md#in-a-hurry) 的章節 _「趕時間?」_。 +9. 這個*路徑操作函式*回傳的不是 dataclass(雖然也可以),而是一個包含內部資料的字典清單。 FastAPI 會使用 `response_model` 參數(其中包含 dataclass)來轉換回應。 diff --git a/docs/zh-hant/docs/advanced/generate-clients.md b/docs/zh-hant/docs/advanced/generate-clients.md index a56877ccd..cc7a6865a 100644 --- a/docs/zh-hant/docs/advanced/generate-clients.md +++ b/docs/zh-hant/docs/advanced/generate-clients.md @@ -20,20 +20,6 @@ FastAPI 會自動產生 **OpenAPI 3.1** 規格,因此你使用的任何工具 /// -## 來自 FastAPI 贊助商的 SDK 產生器 { #sdk-generators-from-fastapi-sponsors } - -本節重點介紹由贊助 FastAPI 的公司提供的**創投支持**與**公司維運**的解決方案。這些產品在高品質的自動產生 SDK 之外,還提供**額外功能**與**整合**。 - -透過 ✨ [**贊助 FastAPI**](../help-fastapi.md#sponsor-the-author) ✨,這些公司幫助確保框架與其**生態系**維持健康且**永續**。 - -他們的贊助也展現對 FastAPI **社群**(你)的高度承諾,不僅關心提供**優良服務**,也支持 **FastAPI** 作為一個**穩健且蓬勃的框架**。🙇 - -例如,你可以嘗試: - -* [Stainless](https://www.stainless.com/?utm_source=fastapi&utm_medium=referral) - -其中有些方案也可能是開源或提供免費方案,讓你不需財務承諾就能試用。其他商業的 SDK 產生器也不少,你可以在網路上找到。🤓 - ## 建立 TypeScript SDK { #create-a-typescript-sdk } 先從一個簡單的 FastAPI 應用開始: @@ -56,7 +42,7 @@ FastAPI 會自動產生 **OpenAPI 3.1** 規格,因此你使用的任何工具 ### Hey API { #hey-api } -當我們有含模型的 FastAPI 應用後,就能用 Hey API 來產生 TypeScript 用戶端。最快的方法是透過 npx: +當我們有含模型的 FastAPI 應用後,就能用 Hey API 來產生 TypeScript 用戶端。最快的方法是透過 npx。 ```sh npx @hey-api/openapi-ts -i http://localhost:8000/openapi.json -o src/client @@ -194,7 +180,7 @@ npx @hey-api/openapi-ts -i ./openapi.json -o src/client 使用自動產生的用戶端時,你會得到以下項目的**自動完成**: * 方法 -* 本文中的請求有效載荷、查詢參數等 +* Body 中的請求有效載荷、查詢參數等 * 回應的有效載荷 你也會對所有內容獲得**行內錯誤**提示。 diff --git a/docs/zh-hant/docs/advanced/json-base64-bytes.md b/docs/zh-hant/docs/advanced/json-base64-bytes.md index 9f1ecfa2e..bdf146b8c 100644 --- a/docs/zh-hant/docs/advanced/json-base64-bytes.md +++ b/docs/zh-hant/docs/advanced/json-base64-bytes.md @@ -4,7 +4,7 @@ ## Base64 與檔案 { #base64-vs-files } -請先考慮是否能用 [請求檔案](../tutorial/request-files.md) 來上傳二進位資料,並用 [自訂回應 - FileResponse](./custom-response.md#fileresponse--fileresponse-) 來傳送二進位資料,而不是把它們編碼進 JSON。 +請先考慮是否能用 [請求檔案](../tutorial/request-files.md) 來上傳二進位資料,並用 [自訂回應 - FileResponse](./custom-response.md#fileresponse) 來傳送二進位資料,而不是把它們編碼進 JSON。 JSON 只能包含 UTF-8 編碼的字串,因此無法直接包含原始位元組。 @@ -14,7 +14,7 @@ Base64 可以把二進位資料編碼成字串,但為此會使用比原始二 ## Pydantic `bytes` { #pydantic-bytes } -你可以宣告含有 `bytes` 欄位的 Pydantic 模型,並在模型設定中使用 `val_json_bytes`,使其在驗證輸入的 JSON 資料時使用 base64;在驗證過程中,它會將 base64 字串解碼為位元組。 +你可以宣告含有 `bytes` 欄位的 Pydantic 模型,並在模型設定中使用 `val_json_bytes`,使其在*驗證*輸入的 JSON 資料時使用 base64;在驗證過程中,它會將 base64 字串解碼為位元組。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:9,29:35] hl[9] *} @@ -52,12 +52,12 @@ Base64 可以把二進位資料編碼成字串,但為此會使用比原始二 ## Pydantic `bytes` 用於輸出資料 { #pydantic-bytes-for-output-data } -你也可以在模型設定中搭配 `ser_json_bytes` 使用 `bytes` 欄位來處理輸出資料;當產生 JSON 回應時,Pydantic 會將位元組以 base64 進行序列化。 +你也可以在模型設定中搭配 `ser_json_bytes` 使用 `bytes` 欄位來處理輸出資料;當產生 JSON 回應時,Pydantic 會將位元組以 base64 進行*序列化*。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,12:16,29,38:41] hl[16] *} ## Pydantic `bytes` 用於輸入與輸出資料 { #pydantic-bytes-for-input-and-output-data } -當然,你也可以使用同一個以 base64 設定的模型,同時處理輸入(以 `val_json_bytes` 驗證)與輸出(以 `ser_json_bytes` 序列化)的 JSON 資料。 +當然,你也可以使用同一個以 base64 設定的模型,同時處理接收與傳送 JSON 資料時的輸入(以 `val_json_bytes` *驗證*)與輸出(以 `ser_json_bytes` *序列化*)。 {* ../../docs_src/json_base64_bytes/tutorial001_py310.py ln[1:2,19:26,29,44:46] hl[23:26] *} diff --git a/docs/zh-hant/docs/advanced/openapi-callbacks.md b/docs/zh-hant/docs/advanced/openapi-callbacks.md index 8b4af6dd3..6ab869acc 100644 --- a/docs/zh-hant/docs/advanced/openapi-callbacks.md +++ b/docs/zh-hant/docs/advanced/openapi-callbacks.md @@ -4,7 +4,7 @@ 當你的 API 應用呼叫「外部 API」時發生的過程稱為「回呼(callback)」。因為外部開發者撰寫的軟體會先向你的 API 發出請求,接著你的 API 再「回呼」,也就是向(可能同一位開發者建立的)外部 API 發送請求。 -在這種情況下,你可能想要文件化說明該外部 API 應該長什麼樣子。它應該有哪些「路徑操作」、應該接受什麼 body、應該回傳什麼 response,等等。 +在這種情況下,你可能想要文件化說明該外部 API 應該長什麼樣子。它應該有哪些「路徑操作」、應該接受什麼 body、應該回傳什麼回應,等等。 ## 帶有回呼的應用 { #an-app-with-callbacks } @@ -82,7 +82,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) 在撰寫回呼的文件化程式碼時,把自己想像成那位「外部開發者」會很有幫助。而且你現在是在實作「外部 API」,不是「你的 API」。 -暫時採用這個(外部開發者)的視角,有助於讓你更直覺地決定該把參數、body 的 Pydantic 模型、response 的模型等放在哪裡,對於那個「外部 API」會更清楚。 +暫時採用這個(外部開發者)的視角,有助於讓你更直覺地決定該把參數、body 的 Pydantic 模型、回應模型等放在哪裡,對於那個「外部 API」會更清楚。 /// @@ -99,7 +99,7 @@ httpx.post(callback_url, json={"description": "Invoice paid", "paid": True}) 它看起來就像一般的 FastAPI「路徑操作」: * 可能需要宣告它應該接收的 body,例如 `body: InvoiceEvent`。 -* 也可以宣告它應該回傳的 response,例如 `response_model=InvoiceEventReceived`。 +* 也可以宣告它應該回傳的回應,例如 `response_model=InvoiceEventReceived`。 {* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *} diff --git a/docs/zh-hant/docs/advanced/response-cookies.md b/docs/zh-hant/docs/advanced/response-cookies.md index 2ba14c3f6..b27552330 100644 --- a/docs/zh-hant/docs/advanced/response-cookies.md +++ b/docs/zh-hant/docs/advanced/response-cookies.md @@ -2,9 +2,9 @@ ## 使用 `Response` 參數 { #use-a-response-parameter } -你可以在路徑操作函式(path operation function)中宣告一個型別為 `Response` 的參數。 +你可以在你的*路徑操作函式*(path operation function)中宣告一個型別為 `Response` 的參數。 -接著你可以在那個「暫時」的 `Response` 物件上設定 Cookie。 +接著你可以在那個*暫時*的 `Response` 物件上設定 Cookie。 {* ../../docs_src/response_cookies/tutorial002_py310.py hl[1, 8:9] *} @@ -12,7 +12,7 @@ 如果你宣告了 `response_model`,它仍會用來過濾並轉換你回傳的物件。 -FastAPI 會使用那個暫時的 `Response` 取出 Cookie(以及標頭與狀態碼),並將它們放入最終回應;最終回應包含你回傳的值,且會套用任何 `response_model` 的過濾。 +**FastAPI** 會使用那個*暫時*的 `Response` 取出 Cookie(以及標頭與狀態碼),並將它們放入最終回應;最終回應包含你回傳的值,且會套用任何 `response_model` 的過濾。 你也可以在相依項(dependencies)中宣告 `Response` 參數,並在其中設定 Cookie(與標頭)。 @@ -42,9 +42,9 @@ FastAPI 會使用那個暫時的 `Response` 取出 Cookie(以及標頭與狀 你也可以使用 `from starlette.responses import Response` 或 `from starlette.responses import JSONResponse`。 -為了方便開發者,FastAPI 也將相同的 `starlette.responses` 透過 `fastapi.responses` 提供。不過,大多數可用的回應類別都直接來自 Starlette。 +**FastAPI** 為了方便你這位開發者,也將相同的 `starlette.responses` 透過 `fastapi.responses` 提供。不過,大多數可用的回應類別都直接來自 Starlette。 -另外由於 `Response` 常用於設定標頭與 Cookie,FastAPI 也在 `fastapi.Response` 提供了它。 +另外由於 `Response` 常用於設定標頭與 Cookie,**FastAPI** 也在 `fastapi.Response` 提供了它。 /// diff --git a/docs/zh-hant/docs/advanced/response-headers.md b/docs/zh-hant/docs/advanced/response-headers.md index 4f7494a8b..002fb0e54 100644 --- a/docs/zh-hant/docs/advanced/response-headers.md +++ b/docs/zh-hant/docs/advanced/response-headers.md @@ -12,7 +12,7 @@ 如果你宣告了 `response_model`,它仍會用來過濾並轉換你回傳的物件。 -FastAPI 會使用那個暫時性的回應來擷取標頭(還有 Cookie 與狀態碼),並把它們放到最終回應中;最終回應包含你回傳的值,且會依任何 `response_model` 進行過濾。 +**FastAPI** 會使用那個暫時性的回應來擷取標頭(還有 Cookie 與狀態碼),並把它們放到最終回應中;最終回應包含你回傳的值,且會依任何 `response_model` 進行過濾。 你也可以在依賴中宣告 `Response` 參數,並在其中設定標頭(與 Cookie)。 @@ -28,9 +28,9 @@ FastAPI 會使用那個暫時性的回應來擷取標頭(還有 Cookie 與狀 你也可以使用 `from starlette.responses import Response` 或 `from starlette.responses import JSONResponse`。 -為了方便開發者,FastAPI 提供與 `starlette.responses` 相同的內容於 `fastapi.responses`。但大多數可用的回應類型其實直接來自 Starlette。 +為了方便開發者,**FastAPI** 提供與 `starlette.responses` 相同的內容於 `fastapi.responses`。但大多數可用的回應類型其實直接來自 Starlette。 -由於 `Response` 常用來設定標頭與 Cookie,FastAPI 也在 `fastapi.Response` 提供了它。 +由於 `Response` 常用來設定標頭與 Cookie,**FastAPI** 也在 `fastapi.Response` 提供了它。 /// diff --git a/docs/zh-hant/docs/advanced/security/oauth2-scopes.md b/docs/zh-hant/docs/advanced/security/oauth2-scopes.md index d0a6ad014..bfd9260e3 100644 --- a/docs/zh-hant/docs/advanced/security/oauth2-scopes.md +++ b/docs/zh-hant/docs/advanced/security/oauth2-scopes.md @@ -1,6 +1,6 @@ # OAuth2 範圍(scopes) { #oauth2-scopes } -你可以直接在 FastAPI 中使用 OAuth2 的 scopes,已整合可無縫運作。 +你可以直接在 **FastAPI** 中使用 OAuth2 的 scopes,已整合可無縫運作。 這能讓你在 OpenAPI 應用(以及 API 文件)中,依照 OAuth2 標準,實作更細粒度的權限系統。 @@ -8,7 +8,7 @@ 每次你「使用」Facebook、Google、GitHub、Microsoft、X(Twitter)「登入」時,那個應用就是在使用帶有 scopes 的 OAuth2。 -在本節中,你將看到如何在你的 FastAPI 應用中,用同樣的帶有 scopes 的 OAuth2 管理驗證與授權。 +在本節中,你將看到如何在你的 **FastAPI** 應用中,用同樣的帶有 scopes 的 OAuth2 管理驗證與授權。 /// warning @@ -42,9 +42,9 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 它們通常用來宣告特定的安全性權限,例如: -- `users:read` 或 `users:write` 是常見的例子。 -- `instagram_basic` 是 Facebook / Instagram 使用的。 -- `https://www.googleapis.com/auth/drive` 是 Google 使用的。 +* `users:read` 或 `users:write` 是常見的例子。 +* `instagram_basic` 是 Facebook / Instagram 使用的。 +* `https://www.googleapis.com/auth/drive` 是 Google 使用的。 /// note @@ -58,9 +58,9 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 /// -## 全局概觀 { #global-view } +## 全域概觀 { #global-view } -先快速看看相對於主教學「使用密碼(與雜湊)、Bearer 與 JWT token 的 OAuth2」的差異([OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md))。現在加入了 OAuth2 scopes: +先快速看看主要 **教學 - 使用者指南** 中 [OAuth2 with Password (and hashing), Bearer with JWT tokens](../../tutorial/security/oauth2-jwt.md) 範例的變更部分。現在加入了 OAuth2 scopes: {* ../../docs_src/security/tutorial005_an_py310.py hl[5,9,13,47,65,106,108:116,122:126,130:136,141,157] *} @@ -84,7 +84,7 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 ## 內含 scopes 的 JWT token { #jwt-token-with-scopes } -現在,修改 token 的路徑操作以回傳所請求的 scopes。 +現在,修改 token 的*路徑操作*以回傳所請求的 scopes。 我們仍然使用相同的 `OAuth2PasswordRequestForm`。它包含屬性 `scopes`,其為 `list` 的 `str`,列出請求中收到的每個 scope。 @@ -100,9 +100,9 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 {* ../../docs_src/security/tutorial005_an_py310.py hl[157] *} -## 在路徑操作與相依性中宣告 scopes { #declare-scopes-in-path-operations-and-dependencies } +## 在*路徑操作*與相依性中宣告 scopes { #declare-scopes-in-path-operations-and-dependencies } -現在我們宣告 `/users/me/items/` 這個路徑操作需要 `items` 這個 scope。 +現在我們宣告 `/users/me/items/` 這個*路徑操作*需要 `items` 這個 scope。 為此,我們從 `fastapi` 匯入並使用 `Security`。 @@ -120,7 +120,7 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 你不一定需要在不同地方加上不同的 scopes。 -我們在這裡這樣做,是為了示範 FastAPI 如何處理在不同層級宣告的 scopes。 +我們在這裡這樣做,是為了示範 **FastAPI** 如何處理在不同層級宣告的 scopes。 /// @@ -130,7 +130,7 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 `Security` 其實是 `Depends` 的子類別,僅多了一個我們稍後會看到的參數。 -改用 `Security` 而不是 `Depends`,能讓 FastAPI 知道可以宣告安全性 scopes、在內部使用它們,並用 OpenAPI 文件化 API。 +改用 `Security` 而不是 `Depends`,能讓 **FastAPI** 知道可以宣告安全性 scopes、在內部使用它們,並用 OpenAPI 文件化 API。 另外,當你從 `fastapi` 匯入 `Query`、`Path`、`Depends`、`Security` 等時,實際上它們是回傳特殊類別的函式。 @@ -184,7 +184,7 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 ## 驗證 `scopes` { #verify-the-scopes } -我們現在要驗證,此相依性與所有相依者(包含路徑操作)所要求的所有 scopes,是否都包含在收到的 token 內所提供的 scopes 中;否則就丟出 `HTTPException`。 +我們現在要驗證,此相依性與所有相依者(包含*路徑操作*)所要求的所有 scopes,是否都包含在收到的 token 內所提供的 scopes 中;否則就丟出 `HTTPException`。 為此,我們使用 `security_scopes.scopes`,其中包含一個 `list`,列出所有這些 `str` 形式的 scopes。 @@ -196,30 +196,30 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 由於 `get_current_active_user` 相依於 `get_current_user`,因此在 `get_current_active_user` 宣告的 `"me"` 這個 scope 會包含在傳給 `get_current_user` 的 `security_scopes.scopes` 的必須 scopes 清單中。 -路徑操作本身也宣告了 `"items"` 這個 scope,因此它也會包含在傳給 `get_current_user` 的 `security_scopes.scopes` 中。 +*路徑操作*本身也宣告了 `"items"` 這個 scope,因此它也會包含在傳給 `get_current_user` 的 `security_scopes.scopes` 中。 以下是相依性與 scopes 的階層關係: -- 路徑操作 `read_own_items` 具有: - - 需要的 scopes `["items"]`,並有相依性: - - `get_current_active_user`: - - 相依函式 `get_current_active_user` 具有: - - 需要的 scopes `["me"]`,並有相依性: - - `get_current_user`: - - 相依函式 `get_current_user` 具有: - - 自身沒有需要的 scopes。 - - 一個使用 `oauth2_scheme` 的相依性。 - - 一個型別為 `SecurityScopes` 的 `security_scopes` 參數: - - 這個 `security_scopes` 參數有屬性 `scopes`,其為一個 `list`,包含了上面宣告的所有 scopes,因此: - - 對於路徑操作 `read_own_items`,`security_scopes.scopes` 會包含 `["me", "items"]`。 - - 對於路徑操作 `read_users_me`,因為它在相依性 `get_current_active_user` 中被宣告,`security_scopes.scopes` 會包含 `["me"]`。 - - 對於路徑操作 `read_system_status`,因為它沒有宣告任何帶 `scopes` 的 `Security`,且其相依性 `get_current_user` 也未宣告任何 `scopes`,所以 `security_scopes.scopes` 會包含 `[]`(空)。 +* *路徑操作* `read_own_items` 具有: + * 需要的 scopes `["items"]`,並有相依性: + * `get_current_active_user`: + * 相依函式 `get_current_active_user` 具有: + * 需要的 scopes `["me"]`,並有相依性: + * `get_current_user`: + * 相依函式 `get_current_user` 具有: + * 自身沒有需要的 scopes。 + * 一個使用 `oauth2_scheme` 的相依性。 + * 一個型別為 `SecurityScopes` 的 `security_scopes` 參數: + * 這個 `security_scopes` 參數有屬性 `scopes`,其為一個 `list`,包含了上面宣告的所有 scopes,因此: + * 對於*路徑操作* `read_own_items`,`security_scopes.scopes` 會包含 `["me", "items"]`。 + * 對於*路徑操作* `read_users_me`,因為它在相依性 `get_current_active_user` 中被宣告,`security_scopes.scopes` 會包含 `["me"]`。 + * 對於*路徑操作* `read_system_status`,因為它沒有宣告任何帶 `scopes` 的 `Security`,且其相依性 `get_current_user` 也未宣告任何 `scopes`,所以 `security_scopes.scopes` 會包含 `[]`(空)。 /// tip -這裡重要且「神奇」的是:`get_current_user` 在每個路徑操作中,會有不同的 `scopes` 清單需要檢查。 +這裡重要且「神奇」的是:`get_current_user` 在每個*路徑操作*中,會有不同的 `scopes` 清單需要檢查。 -這完全取決於該路徑操作與其相依性樹中每個相依性所宣告的 `scopes`。 +這完全取決於該特定*路徑操作*與其相依性樹中每個相依性所宣告的 `scopes`。 /// @@ -227,11 +227,11 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 你可以在任意位置、多個地方使用 `SecurityScopes`,它不需要位於「根」相依性。 -它會永遠帶有對於「該特定」路徑操作與「該特定」相依性樹中,目前 `Security` 相依性所宣告的安全性 scopes(以及所有相依者): +它會永遠帶有對於**該特定***路徑操作*與**該特定**相依性樹中,目前 `Security` 相依性所宣告的安全性 scopes(以及所有相依者)。 -因為 `SecurityScopes` 會擁有由相依者宣告的所有 scopes,你可以在一個集中式相依函式中用它來驗證 token 是否具有所需 scopes,然後在不同路徑操作中宣告不同的 scope 要求。 +因為 `SecurityScopes` 會擁有由相依者宣告的所有 scopes,你可以在一個集中式相依函式中用它來驗證 token 是否具有所需 scopes,然後在不同*路徑操作*中宣告不同的 scope 要求。 -它們會在每個路徑操作被各自獨立檢查。 +它們會在每個*路徑操作*被各自獨立檢查。 ## 試用看看 { #check-it } @@ -241,9 +241,9 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 如果你沒有選任何 scope,你仍會「通過驗證」,但當你嘗試存取 `/users/me/` 或 `/users/me/items/` 時,會收到沒有足夠權限的錯誤。你仍能存取 `/status/`。 -若你只選了 `me` 而未選 `items`,你能存取 `/users/me/`,但無法存取 `/users/me/items/`。 +若你只選了 `me` 這個 scope 而未選 `items` 這個 scope,你能存取 `/users/me/`,但無法存取 `/users/me/items/`。 -這就是第三方應用在取得使用者提供的 token 後,嘗試存取上述路徑操作時,會依使用者授與該應用的權限多寡而有不同結果。 +這就是第三方應用在取得使用者提供的 token 後,嘗試存取上述其中一個*路徑操作*時,會依使用者授與該應用的權限多寡而有不同結果。 ## 關於第三方整合 { #about-third-party-integrations } @@ -255,9 +255,9 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 但如果你要打造一個讓他人連接的 OAuth2 應用(也就是你要建立一個相當於 Facebook、Google、GitHub 等的身分驗證提供者),你應該使用其他流程之一。 -最常見的是 Implicit Flow(隱式流程)。 +最常見的是 implicit flow(隱式流程)。 -最安全的是 Authorization Code Flow(授權碼流程),但它需要更多步驟、實作也更複雜。因為較複雜,許多提供者最後會建議使用隱式流程。 +最安全的是 code flow(授權碼流程),但它需要更多步驟、實作也更複雜。因為較複雜,許多提供者最後會建議使用隱式流程。 /// note @@ -267,7 +267,7 @@ OAuth2 規格將「scopes」定義為以空白分隔的一串字串列表。 /// -FastAPI 在 `fastapi.security.oauth2` 中提供了所有這些 OAuth2 驗證流程的工具。 +**FastAPI** 在 `fastapi.security.oauth2` 中提供了所有這些 OAuth2 驗證流程的工具。 ## 在裝飾器 `dependencies` 中使用 `Security` { #security-in-decorator-dependencies } diff --git a/docs/zh-hant/docs/advanced/settings.md b/docs/zh-hant/docs/advanced/settings.md index 9892f8f00..4ec1ea672 100644 --- a/docs/zh-hant/docs/advanced/settings.md +++ b/docs/zh-hant/docs/advanced/settings.md @@ -297,6 +297,6 @@ participant execute as Execute function 你可以使用 Pydantic Settings 來處理應用程式的設定或組態,並享有 Pydantic model 的全部能力。 -- 透過相依可以讓測試更容易。 -- 你可以搭配 `.env` 檔使用。 -- 使用 `@lru_cache` 可以避免每個請求都重複讀取 dotenv 檔,同時仍可在測試時覆寫設定。 +* 透過相依可以讓測試更容易。 +* 你可以搭配 `.env` 檔使用。 +* 使用 `@lru_cache` 可以避免每個請求都重複讀取 dotenv 檔,同時仍可在測試時覆寫設定。 diff --git a/docs/zh-hant/docs/advanced/stream-data.md b/docs/zh-hant/docs/advanced/stream-data.md index d28cd35ec..c38c48faf 100644 --- a/docs/zh-hant/docs/advanced/stream-data.md +++ b/docs/zh-hant/docs/advanced/stream-data.md @@ -2,7 +2,7 @@ 如果你要串流可用 JSON 結構化的資料,應該[串流 JSON Lines](../tutorial/stream-json-lines.md)。 -但如果你想串流純二進位資料或字串,以下是做法。 +但如果你想**串流純二進位資料**或字串,以下是做法。 /// note @@ -12,11 +12,11 @@ ## 使用情境 { #use-cases } -當你想串流純字串時可以用這個機制,例如直接轉發來自 AI LLM 服務的輸出。 +當你想串流純字串時可以用這個機制,例如直接轉發來自 **AI LLM** 服務的輸出。 -你也可以用它來串流大型二進位檔案,邊讀邊將每個區塊(chunk)串流出去,而不必一次把整個檔案載入記憶體。 +你也可以用它來串流**大型二進位檔案**,邊讀邊將每個區塊(chunk)串流出去,而不必一次把整個檔案載入記憶體。 -你也可以用同樣方式串流視訊或音訊,甚至可以在處理的同時即時產生並傳送。 +你也可以用同樣方式串流**視訊**或**音訊**,甚至可以在處理的同時即時產生並傳送。 ## 使用 `yield` 的 `StreamingResponse` { #a-streamingresponse-with-yield } @@ -40,7 +40,7 @@ FastAPI 會如實將每個資料區塊交給 `StreamingResponse`,不會嘗試 {* ../../docs_src/stream_data/tutorial001_py310.py ln[32:35] hl[33] *} -這也意味著使用 `StreamingResponse` 時,你擁有自由與責任,需依需求自行產生並編碼要傳送的位元組資料,與型別註解無關。 🤓 +這也意味著使用 `StreamingResponse` 時,你擁有**自由**與**責任**,需依需求自行產生並編碼要傳送的位元組資料,與型別註解無關。 🤓 ### 串流位元組 { #stream-bytes } diff --git a/docs/zh-hant/docs/deployment/cloud.md b/docs/zh-hant/docs/deployment/cloud.md index 86d216ca6..caf05ec16 100644 --- a/docs/zh-hant/docs/deployment/cloud.md +++ b/docs/zh-hant/docs/deployment/cloud.md @@ -16,7 +16,7 @@ FastAPI Cloud 是 *FastAPI and friends* 開源專案的主要贊助與資金提 ## 雲端供應商 - 贊助商 { #cloud-providers-sponsors } -其他一些雲端供應商也會 ✨ [**贊助 FastAPI**](../help-fastapi.md#sponsor-the-author) ✨。🙇 +其他一些雲端供應商也會 ✨ [**贊助 FastAPI**](https://github.com/sponsors/tiangolo) ✨。🙇 你也可以參考他們的指南並試用其服務: diff --git a/docs/zh-hant/docs/deployment/docker.md b/docs/zh-hant/docs/deployment/docker.md index 650873887..b10299def 100644 --- a/docs/zh-hant/docs/deployment/docker.md +++ b/docs/zh-hant/docs/deployment/docker.md @@ -258,7 +258,7 @@ CMD fastapi run app/main.py --port 80 你可以在 [Docker 關於 shell 與 exec 形式的文件](https://docs.docker.com/reference/dockerfile/#shell-and-exec-form) 閱讀更多。 -使用 `docker compose` 時這會特別明顯。技術細節請見這段 Docker Compose 常見問題:[為什麼我的服務要花 10 秒才重新建立或停止?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop) +使用 `docker compose` 時這會特別明顯。技術細節請見這段 Docker Compose 常見問題:[為什麼我的服務要花 10 秒才重新建立或停止?](https://docs.docker.com/compose/faq/#why-do-my-services-take-10-seconds-to-recreate-or-stop)。 #### 目錄結構 { #directory-structure } @@ -454,7 +454,7 @@ Traefik 與 Docker、Kubernetes 等整合良好,因此為你的容器設定與 ## 複本 - 行程數量 { #replication-number-of-processes } -如果你在有 Kubernetes、Docker Swarm Mode、Nomad,或其他類似的分散式容器管理系統的「叢集」上運作,那你大概會希望在「叢集層級」處理「複本」,而不是在每個容器內使用「行程管理器」(例如帶有 workers 的 Uvicorn)。 +如果你在有 Kubernetes、Docker Swarm Mode、Nomad,或其他類似的分散式容器管理系統的「叢集」上運作,那你大概會希望在「叢集層級」處理「複本」,而不是在每個容器內使用「行程管理器」(例如帶有 workers 的 Uvicorn)。 像 Kubernetes 這類的分散式容器管理系統,通常內建處理「容器複本」以及支援進入請求的「負載平衡」的能力——全部都在「叢集層級」。 @@ -574,7 +574,7 @@ CMD ["fastapi", "run", "app/main.py", "--port", "80", "--workers", "4"] 你大概「不應該」使用這個基底 Docker 映像(或其他類似的)。 -如果你使用 Kubernetes(或其他)並已在叢集層級設定「複本」、使用多個「容器」。在這些情況下,更好的做法是如上所述[從零建置映像](#build-a-docker-image-for-fastapi)。 +如果你使用 Kubernetes(或其他)並已在叢集層級設定「複本」、使用多個「容器」。在這些情況下,更好的做法是如上所述「從零建置映像」:[為 FastAPI 建置 Docker 映像](#build-a-docker-image-for-fastapi)。 若你需要多個 workers,只要使用 `--workers` 命令列選項即可。 diff --git a/docs/zh-hant/docs/deployment/manually.md b/docs/zh-hant/docs/deployment/manually.md index 2260f6942..590d0b011 100644 --- a/docs/zh-hant/docs/deployment/manually.md +++ b/docs/zh-hant/docs/deployment/manually.md @@ -40,7 +40,7 @@ $ fastapi run fastapi run ASGI。FastAPI 是一個 ASGI 網頁框架。 -在遠端伺服器機器上執行 FastAPI 應用(或任何 ASGI 應用)所需的關鍵是 ASGI 伺服器程式,例如 Uvicorn;`fastapi` 指令預設就是使用它。 +在遠端伺服器機器上執行 **FastAPI** 應用(或任何 ASGI 應用)所需的關鍵是 ASGI 伺服器程式,例如 **Uvicorn**;`fastapi` 指令預設就是使用它。 有數個替代方案,包括: @@ -61,11 +61,11 @@ FastAPI 採用建立 Python 網頁框架與伺服器的標準 @@ -34,7 +34,7 @@ {* ../../docs_src/separate_openapi_schemas/tutorial001_py310.py hl[19] *} -...由於 `description` 有預設值,就算你沒有為該欄位回傳任何內容,它仍會有那個預設值。 +...由於 `description` 有預設值,就算你**沒有為該欄位回傳任何內容**,它仍會有那個**預設值**。 ### 輸出回應資料的模型 { #model-for-output-response-data } @@ -44,20 +44,20 @@ -這代表該欄位一定會有值,只是有時候值可能是 `None`(在 JSON 中為 `null`)。 +這代表該欄位**一定會有值**,只是有時候值可能是 `None`(在 JSON 中為 `null`)。 -因此,使用你 API 的用戶端不必檢查值是否存在,可以假設該欄位一定存在;只是有些情況下它的值會是預設的 `None`。 +因此,使用你 API 的用戶端不必檢查值是否存在,可以**假設該欄位一定存在**;只是有些情況下它的值會是預設的 `None`。 -在 OpenAPI 中,描述這種情況的方式是將該欄位標記為必填,因為它一定存在。 +在 OpenAPI 中,描述這種情況的方式是將該欄位標記為**必填**,因為它一定存在。 -因此,同一個模型的 JSON Schema 會依用於輸入或輸出而不同: +因此,同一個模型的 JSON Schema 會依用於**輸入或輸出**而不同: -- 用於輸入時,`description` 不是必填 -- 用於輸出時,`description` 是必填(且可能為 `None`,在 JSON 中為 `null`) +* 用於**輸入**時,`description` **不是必填** +* 用於**輸出**時,`description` 是**必填**(且可能為 `None`,在 JSON 中為 `null`) ### 文件中的輸出模型 { #model-for-output-in-docs } -你也可以在文件中檢視輸出模型,`name` 與 `description` 都以紅色星號標示為必填: +你也可以在文件中檢視輸出模型,`name` 與 `description` **兩者**都以**紅色星號**標示為**必填**:
@@ -67,23 +67,23 @@ 如果你查看 OpenAPI 中所有可用的結構描述(JSON Schema),會看到有兩個:`Item-Input` 與 `Item-Output`。 -對於 `Item-Input`,`description` 不是必填,沒有紅色星號。 +對於 `Item-Input`,`description` **不是必填**,沒有紅色星號。 -但對於 `Item-Output`,`description` 是必填,有紅色星號。 +但對於 `Item-Output`,`description` 是**必填**,有紅色星號。
-有了 Pydantic v2 的這個特性,你的 API 文件會更精確;若你有自動產生的用戶端與 SDK,它們也會更精確,提供更好的開發者體驗與一致性。🎉 +有了 **Pydantic v2** 的這個特性,你的 API 文件會更**精確**;若你有自動產生的用戶端與 SDK,它們也會更精確,提供更好的**開發者體驗**與一致性。🎉 ## 不要分開結構描述 { #do-not-separate-schemas } -不過,在某些情況下,你可能會希望輸入與輸出使用相同的結構描述。 +不過,在某些情況下,你可能會希望**輸入與輸出使用相同的結構描述**。 最常見的情境是:你已經有一些自動產生的用戶端程式碼/SDK,目前還不想全部更新;也許之後會做,但不是現在。 -在這種情況下,你可以在 FastAPI 中透過參數 `separate_input_output_schemas=False` 停用這個功能。 +在這種情況下,你可以在 **FastAPI** 中透過參數 `separate_input_output_schemas=False` 停用這個功能。 /// note @@ -95,7 +95,7 @@ ### 文件中輸入與輸出使用相同結構描述的模型 { #same-schema-for-input-and-output-models-in-docs } -此時輸入與輸出將共用同一個模型結構描述,只有 `Item`,其中 `description` 不是必填: +此時輸入與輸出將共用同一個模型結構描述,只有 `Item`,其中 `description` **不是必填**:
diff --git a/docs/zh-hant/docs/tutorial/bigger-applications.md b/docs/zh-hant/docs/tutorial/bigger-applications.md index 60dd4f350..7ebf59a74 100644 --- a/docs/zh-hant/docs/tutorial/bigger-applications.md +++ b/docs/zh-hant/docs/tutorial/bigger-applications.md @@ -542,6 +542,6 @@ router.include_router(other_router) 請使用有文件記載的 API,例如路徑操作的裝飾器與 `.include_router()` 來新增路由與 routers。 -把 `router.routes` 視為較低階的路由樹結構,它可能同時包含路由定義與被納入的 routers,避免將它當成最終路徑操作的平lat清單來依賴。 +把 `router.routes` 視為較低階的路由樹結構,它可能同時包含路由定義與被納入的 routers,避免將它當成最終路徑操作的扁平清單來依賴。 /// diff --git a/docs/zh-hant/docs/tutorial/body.md b/docs/zh-hant/docs/tutorial/body.md index aff55730b..f1ba8e954 100644 --- a/docs/zh-hant/docs/tutorial/body.md +++ b/docs/zh-hant/docs/tutorial/body.md @@ -32,6 +32,7 @@ {* ../../docs_src/body/tutorial001_py310.py hl[5:9] *} + 就和宣告查詢參數時一樣,當模型屬性有預設值時,它就不是必填;否則就是必填。使用 `None` 可使其成為選填。 例如,上述模型對應的 JSON「`object`」(或 Python `dict`)如下: @@ -135,6 +136,7 @@ {* ../../docs_src/body/tutorial003_py310.py hl[15:16] *} + ## 請求本文 + 路徑 + 查詢參數 { #request-body-path-query-parameters } 你也可以同時宣告**本文**、**路徑**與**查詢**參數。 diff --git a/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md b/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md index 59d575fb0..c41f3ba7d 100644 --- a/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md +++ b/docs/zh-hant/docs/tutorial/dependencies/dependencies-with-yield.md @@ -234,6 +234,7 @@ participant operation as Path Operation 含 `yield` 的相依隨時間演進,以涵蓋不同的使用情境並修正一些問題。 如果你想了解在不同 FastAPI 版本中改了哪些內容,可以在進階指南中閱讀:[進階相依 — 含 `yield`、`HTTPException`、`except` 與背景任務的相依](../../advanced/advanced-dependencies.md#dependencies-with-yield-httpexception-except-and-background-tasks)。 + ## 情境管理器 { #context-managers } ### 什麼是「情境管理器」 { #what-are-context-managers } diff --git a/docs/zh-hant/docs/tutorial/extra-models.md b/docs/zh-hant/docs/tutorial/extra-models.md index f5509f531..162325e9d 100644 --- a/docs/zh-hant/docs/tutorial/extra-models.md +++ b/docs/zh-hant/docs/tutorial/extra-models.md @@ -4,9 +4,9 @@ 對使用者模型尤其如此,因為: -* 「輸入模型」需要能包含密碼。 -* 「輸出模型」不應包含密碼。 -* 「資料庫模型」通常需要儲存雜湊後的密碼。 +* **輸入模型**需要能包含密碼。 +* **輸出模型**不應包含密碼。 +* **資料庫模型**通常需要儲存雜湊後的密碼。 /// danger @@ -140,7 +140,7 @@ UserInDB( ## 減少重複 { #reduce-duplication } -減少程式碼重複是 FastAPI 的核心理念之一。 +減少程式碼重複是 **FastAPI** 的核心理念之一。 因為重複的程式碼會提高發生錯誤、安全性問題、程式不同步(某處更新但其他處未更新)等風險。 @@ -176,7 +176,7 @@ UserInDB( 此範例中,我們將 `Union[PlaneItem, CarItem]` 作為引數 `response_model` 的值。 -由於這裡是把它當作引數的「值」傳入,而非用於型別註記,因此即使在 Python 3.10 也必須使用 `Union`。 +由於這裡是把它當作**引數的值**傳入,而非放在**型別註記**中,因此即使在 Python 3.10 也必須使用 `Union`。 若用於型別註記,則可以使用直線(|),如下: @@ -184,7 +184,7 @@ UserInDB( some_variable: PlaneItem | CarItem ``` -但若寫成指定值 `response_model=PlaneItem | CarItem` 會發生錯誤,因為 Python 會嘗試在 `PlaneItem` 與 `CarItem` 之間執行「無效運算」,而非將其視為型別註記。 +但若寫成指定值 `response_model=PlaneItem | CarItem` 會發生錯誤,因為 Python 會嘗試在 `PlaneItem` 與 `CarItem` 之間執行**無效運算**,而非將其視為型別註記。 ## 模型的清單 { #list-of-models } @@ -208,4 +208,4 @@ some_variable: PlaneItem | CarItem 依情境使用多個 Pydantic 模型並靈活繼承。 -當一個實體需要呈現不同「狀態」時,不必侷限於一個資料模型。例如使用者這個實體,可能有包含 `password`、包含 `password_hash`,或不含密碼等不同狀態。 +當一個實體需要呈現不同「狀態」時,不必侷限於一個資料模型。**使用者**「實體」是一個例子,可能有包含 `password`、包含 `password_hash`,或不含密碼等不同狀態。 diff --git a/docs/zh-hant/docs/tutorial/first-steps.md b/docs/zh-hant/docs/tutorial/first-steps.md index 8d644abd1..bc023cc39 100644 --- a/docs/zh-hant/docs/tutorial/first-steps.md +++ b/docs/zh-hant/docs/tutorial/first-steps.md @@ -137,9 +137,9 @@ OpenAPI 為你的 API 定義了 API 的 schema。而該 schema 會包含你的 A #### OpenAPI 的用途 { #what-is-openapi-for } -OpenAPI schema 驅動了兩個互動式文件系統。 +OpenAPI schema 驅動了內建的兩個互動式文件系統。 -而且有許多替代方案,所有這些都是基於 OpenAPI。你可以輕鬆地將任何這些替代方案添加到使用 **FastAPI** 建置的應用程式中。 +而且有數十種替代方案,所有這些都是基於 OpenAPI。你可以輕鬆地將任何這些替代方案加入到使用 **FastAPI** 建置的應用程式中。 你也可以用它自動生成程式碼,讓用戶端與你的 API 通訊。例如前端、手機或物聯網(IoT)應用程式。 @@ -226,7 +226,7 @@ CLI 會自動偵測你的 FastAPI 應用並將它部署到雲端。若你尚未 {* ../../docs_src/first_steps/tutorial001_py310.py hl[1] *} -`FastAPI` 是一個 Python 類別,提供所有 API 的全部功能。 +`FastAPI` 是一個 Python 類別,提供你的 API 所需的所有功能。 /// note | 技術細節 @@ -244,7 +244,7 @@ CLI 會自動偵測你的 FastAPI 應用並將它部署到雲端。若你尚未 這將是你建立所有 API 的主要互動點。 -### 第三步:建立一個「路徑操作」 { #step-3-create-a-path-operation } +### 第三步:建立一個*路徑操作* { #step-3-create-a-path-operation } #### 路徑 { #path } @@ -256,7 +256,7 @@ CLI 會自動偵測你的 FastAPI 應用並將它部署到雲端。若你尚未 https://example.com/items/foo ``` -……的路徑將會是: +...的路徑將會是: ``` /items/foo @@ -281,7 +281,7 @@ https://example.com/items/foo * `PUT` * `DELETE` -……以及更少見的: +...以及更少見的: * `OPTIONS` * `HEAD` @@ -305,14 +305,14 @@ https://example.com/items/foo 我們將會稱它們為「**操作**」。 -#### 定義一個「路徑操作裝飾器」 { #define-a-path-operation-decorator } +#### 定義一個*路徑操作裝飾器* { #define-a-path-operation-decorator } {* ../../docs_src/first_steps/tutorial001_py310.py hl[6] *} -`@app.get("/")` 告訴 **FastAPI** 那個函式負責處理請求: +`@app.get("/")` 告訴 **FastAPI** 正下方的函式負責處理前往以下位置的請求: * 路徑 `/` -* 使用 get 操作 +* 使用 get 操作 /// note | `@decorator` 說明 @@ -353,7 +353,7 @@ Python 中的 `@something` 語法被稱為「裝飾器」。 /// -### 第四步:定義「路徑操作函式」 { #step-4-define-the-path-operation-function } +### 第四步:定義**路徑操作函式** { #step-4-define-the-path-operation-function } 這是我們的「**路徑操作函式**」: @@ -377,7 +377,7 @@ Python 中的 `@something` 語法被稱為「裝飾器」。 /// note -如果你不知道差別,請查看 [Async: *"In a hurry?"*](../async.md#in-a-hurry)。 +如果你不知道差別,請查看 [Async:*「很趕時間?」*](../async.md#in-a-hurry)。 /// @@ -399,11 +399,11 @@ Python 中的 `@something` 語法被稱為「裝飾器」。 **[FastAPI Cloud](https://fastapicloud.com)** 由 **FastAPI** 的作者與團隊打造。 -它讓你以最小的成本完成 API 的**建置**、**部署**與**存取**流程。 +它讓你以最少的心力簡化 API 的**建置**、**部署**與**存取**流程。 它把用 FastAPI 開發應用的同樣**開發者體驗**帶到將應用**部署**到雲端的流程中。🎉 -FastAPI Cloud 也是「FastAPI 與其好友」這些開源專案的主要贊助與資金提供者。✨ +FastAPI Cloud 也是 *FastAPI 與其好友* 這些開源專案的主要贊助與資金提供者。✨ #### 部署到其他雲端供應商 { #deploy-to-other-cloud-providers } @@ -415,7 +415,7 @@ FastAPI 是開源並基於標準的。你可以把 FastAPI 應用部署到你選 * 引入 `FastAPI`。 * 建立一個 `app` 實例。 -* 寫一個「路徑操作裝飾器」,像是 `@app.get("/")`。 -* 定義一個「路徑操作函式」;例如,`def root(): ...`。 +* 寫一個**路徑操作裝飾器**,像是 `@app.get("/")`。 +* 定義一個**路徑操作函式**;例如,`def root(): ...`。 * 使用命令 `fastapi dev` 執行開發伺服器。 * 可選:使用 `fastapi deploy` 部署你的應用程式。 diff --git a/docs/zh-hant/docs/tutorial/handling-errors.md b/docs/zh-hant/docs/tutorial/handling-errors.md index b1ffd3e03..dc6d7a7cc 100644 --- a/docs/zh-hant/docs/tutorial/handling-errors.md +++ b/docs/zh-hant/docs/tutorial/handling-errors.md @@ -11,13 +11,13 @@ * 用戶端嘗試存取的項目不存在。 * 等等。 -在這些情況下,通常會回傳範圍為 400(400 到 499)的 HTTP 狀態碼。 +在這些情況下,通常會回傳範圍為 **400**(400 到 499)的 **HTTP 狀態碼**。 這類似於 200 範圍的 HTTP 狀態碼(200 到 299)。那些「200」狀態碼表示請求在某種程度上是「成功」的。 400 範圍的狀態碼表示用戶端錯誤。 -還記得那些「404 Not Found」錯誤(和梗)嗎? +還記得那些 **「404 Not Found」** 錯誤(和梗)嗎? ## 使用 `HTTPException` { #use-httpexception } diff --git a/docs/zh-hant/docs/tutorial/index.md b/docs/zh-hant/docs/tutorial/index.md index e19121511..e20c9ca24 100644 --- a/docs/zh-hant/docs/tutorial/index.md +++ b/docs/zh-hant/docs/tutorial/index.md @@ -98,4 +98,4 @@ FastAPI 提供了 [VS Code 官方擴充功能](https://marketplace.visualstudio. 但首先你應該閱讀**教學 - 使用者指南**(你正在閱讀的內容)。 -它被設計成你可以使用**教學 - 使用者指南**來建立一個完整的應用程式,然後根據你的需求,使用一些額外的想法來擴展它。 +它被設計成你可以使用**教學 - 使用者指南**來建立一個完整的應用程式,然後根據你的需求,使用**進階使用者指南**中的一些額外想法,以不同方式擴展它。 diff --git a/docs/zh-hant/docs/tutorial/metadata.md b/docs/zh-hant/docs/tutorial/metadata.md index 6a54724a5..55fa4bdbf 100644 --- a/docs/zh-hant/docs/tutorial/metadata.md +++ b/docs/zh-hant/docs/tutorial/metadata.md @@ -1,6 +1,6 @@ # 中繼資料與文件 URL { #metadata-and-docs-urls } -你可以在你的 FastAPI 應用程式中自訂多項中繼資料設定。 +你可以在你的 **FastAPI** 應用程式中自訂多項中繼資料設定。 ## API 的中繼資料 { #metadata-for-api } @@ -11,7 +11,7 @@ | `title` | `str` | API 的標題。 | | `summary` | `str` | API 的簡短摘要。自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。 | | `description` | `str` | API 的簡短說明。可使用 Markdown。 | -| `version` | `string` | API 的版本號。這是你自己的應用程式版本,不是 OpenAPI 的版本,例如 `2.5.0`。 | +| `version` | `str` | API 的版本號。這是你自己的應用程式版本,不是 OpenAPI 的版本,例如 `2.5.0`。 | | `terms_of_service` | `str` | 指向 API 服務條款的 URL。若提供,必須是 URL。 | | `contact` | `dict` | 對外公開的 API 聯絡資訊。可包含多個欄位。
contact 欄位
參數型別說明
namestr聯絡人/組織的識別名稱。
urlstr指向聯絡資訊的 URL。必須是 URL 格式。
emailstr聯絡人/組織的電子郵件地址。必須是電子郵件格式。
| | `license_info` | `dict` | 對外公開的 API 授權資訊。可包含多個欄位。
license_info 欄位
參數型別說明
namestr必填(若有設定 license_info)。API 使用的授權名稱。
identifierstrAPI 的 [SPDX](https://spdx.org/licenses/) 授權表示式。identifier 欄位與 url 欄位互斥。自 OpenAPI 3.1.0、FastAPI 0.99.0 起可用。
urlstrAPI 所採用授權的 URL。必須是 URL 格式。
| @@ -46,7 +46,7 @@ 每個 dictionary 可包含: -* `name`(**必填**):一個 `str`,其值需與你在路徑操作與 `APIRouter`s 的 `tags` 參數中使用的標籤名稱相同。 +* `name`(**必填**):一個 `str`,其值需與你在*路徑操作*與 `APIRouter`s 的 `tags` 參數中使用的標籤名稱相同。 * `description`:一個 `str`,為該標籤的簡短描述。可使用 Markdown,並會顯示在文件介面中。 * `externalDocs`:一個 `dict`,描述外部文件,包含: * `description`:一個 `str`,外部文件的簡短描述。 @@ -70,7 +70,7 @@ ### 使用你的標籤 { #use-your-tags } -在你的路徑操作(以及 `APIRouter`s)上使用 `tags` 參數,將它們歸類到不同標籤下: +在你的*路徑操作*(以及 `APIRouter`s)上使用 `tags` 參數,將它們歸類到不同標籤下: {* ../../docs_src/metadata/tutorial004_py310.py hl[21,26] *} @@ -108,10 +108,10 @@ 你可以設定內建的兩個文件使用者介面: -* Swagger UI:提供於 `/docs`。 +* **Swagger UI**:提供於 `/docs`。 * 可用 `docs_url` 參數設定其 URL。 * 設定 `docs_url=None` 可停用。 -* ReDoc:提供於 `/redoc`。 +* **ReDoc**:提供於 `/redoc`。 * 可用 `redoc_url` 參數設定其 URL。 * 設定 `redoc_url=None` 可停用。 diff --git a/docs/zh-hant/docs/tutorial/query-params-str-validations.md b/docs/zh-hant/docs/tutorial/query-params-str-validations.md index 1c247b0f8..99690708e 100644 --- a/docs/zh-hant/docs/tutorial/query-params-str-validations.md +++ b/docs/zh-hant/docs/tutorial/query-params-str-validations.md @@ -1,6 +1,6 @@ # 查詢參數與字串驗證 { #query-parameters-and-string-validations } -FastAPI 允許你為參數宣告額外的資訊與驗證。 +**FastAPI** 允許你為參數宣告額外的資訊與驗證。 以下面這個應用為例: @@ -18,14 +18,14 @@ FastAPI 會因為預設值是 `= None` 而知道 `q` 不是必填。 ## 額外驗證 { #additional-validation } -我們要強制:即使 `q` 是可選,只要提供了,長度就不能超過 50 個字元。 +我們要強制:即使 `q` 是可選,只要提供了,**長度就不能超過 50 個字元**。 ### 匯入 `Query` 與 `Annotated` { #import-query-and-annotated } 要達成這點,先匯入: -- 從 `fastapi` 匯入 `Query` -- 從 `typing` 匯入 `Annotated` +* 從 `fastapi` 匯入 `Query` +* 從 `typing` 匯入 `Annotated` {* ../../docs_src/query_params_str_validations/tutorial002_an_py310.py hl[1,3] *} @@ -69,19 +69,19 @@ q: Annotated[str | None] = None 注意預設值仍然是 `None`,所以這個參數仍是可選。 -不過,現在在 `Annotated` 裡有 `Query(max_length=50)`,我們就告訴 FastAPI 要對這個值做「額外驗證」,最多 50 個字元即可。😎 +不過,現在在 `Annotated` 裡有 `Query(max_length=50)`,我們就告訴 FastAPI 要對這個值做**額外驗證**,最多 50 個字元即可。😎 /// tip | 提示 -這裡用的是 `Query()`,因為這是「查詢參數」。稍後你會看到 `Path()`、`Body()`、`Header()`、`Cookie()` 等,它們也接受與 `Query()` 相同的參數。 +這裡用的是 `Query()`,因為這是**查詢參數**。稍後你會看到 `Path()`、`Body()`、`Header()`、`Cookie()` 等,它們也接受與 `Query()` 相同的參數。 /// FastAPI 現在會: -- 驗證資料,確保長度最多 50 個字元 -- 當資料不合法時,回給用戶端清楚的錯誤 -- 在 OpenAPI 的路徑操作中文件化該參數(因此會出現在自動文件 UI) +* **驗證**資料,確保長度最多 50 個字元 +* 當資料不合法時,回給用戶端**清楚的錯誤** +* 在 OpenAPI schema *路徑操作*中**文件化**該參數(因此會出現在**自動文件 UI**) ## 替代方式(舊):將 `Query` 作為預設值 { #alternative-old-query-as-the-default-value } @@ -105,7 +105,8 @@ FastAPI 現在會: q: str | None = Query(default=None) ``` -…會讓參數變為可選、預設值是 `None`,等同於: +...會讓參數變為可選、預設值是 `None`,等同於: + ```Python q: str | None = None @@ -119,7 +120,7 @@ q: str | None = None q: str | None = Query(default=None, max_length=50) ``` -這一樣會驗證資料、在資料不合法時顯示清楚錯誤,並在 OpenAPI 的路徑操作中文件化該參數。 +這一樣會驗證資料、在資料不合法時顯示清楚錯誤,並在 OpenAPI schema *路徑操作*中文件化該參數。 ### 將 `Query` 作為預設值或放在 `Annotated` 中 { #query-as-the-default-value-or-in-annotated } @@ -133,7 +134,7 @@ q: str | None = Query(default=None, max_length=50) q: Annotated[str, Query(default="rick")] = "morty" ``` -…因為不清楚預設值到底該是 `"rick"` 還是 `"morty"`。 +...因為不清楚預設值到底該是 `"rick"` 還是 `"morty"`。 因此,你可以(且更推薦)這樣寫: @@ -141,7 +142,7 @@ q: Annotated[str, Query(default="rick")] = "morty" q: Annotated[str, Query()] = "rick" ``` -…或在較舊的程式碼中你會看到: +...或在較舊的程式碼中你會看到: ```Python q: str = Query(default="rick") @@ -149,13 +150,13 @@ q: str = Query(default="rick") ### `Annotated` 的優點 { #advantages-of-annotated } -建議使用 `Annotated`,而不是在函式參數上使用(舊式的)預設值寫法,理由很多,且更好。🤓 +建議**使用 `Annotated`**,而不是在函式參數上使用預設值寫法,理由很多,且**更好**。🤓 -函式參數的「預設值」就是「實際的預設值」,這在 Python 的直覺上更一致。😌 +函式參數的**預設值**就是**實際的預設值**,這在 Python 的直覺上更一致。😌 -你也可以在沒有 FastAPI 的其他地方「直接呼叫」同一個函式,而且能「如預期」運作。若有「必填」參數(沒有預設值),你的「編輯器」會提示錯誤,「Python」在執行時也會抱怨你未傳遞必填參數。 +你也可以在沒有 FastAPI 的**其他地方**「**呼叫**」同一個函式,而且能「**如預期**」運作。若有**必填**參數(沒有預設值),你的**編輯器**會提示錯誤,**Python** 在執行時也會抱怨你未傳遞必填參數。 -若不使用 `Annotated`、改用「(舊式)預設值」寫法,你在沒有 FastAPI 的「其他地方」呼叫該函式時,就得「記得」傳入正確參數,否則值會和預期不同(例如會得到 `QueryInfo` 或類似的東西,而不是 `str`)。你的編輯器不會提示,Python 執行該函式時也不會抱怨,只有在內部操作失敗時才會出錯。 +若不使用 `Annotated`、改用**(舊式)預設值**寫法,你在沒有 FastAPI 的**其他地方**呼叫該函式時,就得**記得**傳入正確參數,否則值會和預期不同(例如會得到 `QueryInfo` 或類似的東西,而不是 `str`)。你的編輯器不會提示,Python 執行該函式時也不會抱怨,只有在內部操作失敗時才會出錯。 因為 `Annotated` 可以有多個中繼資料註解,你甚至可以用同一個函式配合其他工具,例如 [Typer](https://typer.tiangolo.com/)。🚀 @@ -167,19 +168,19 @@ q: str = Query(default="rick") ## 加入正規表示式 { #add-regular-expressions } -你可以定義參數必須符合的 正規表示式 `pattern`: +你可以定義參數必須符合的 正規表示式 `pattern`: {* ../../docs_src/query_params_str_validations/tutorial004_an_py310.py hl[11] *} 這個特定的正規表示式樣式會檢查收到的參數值是否: -- `^`:以後續的字元開頭,前面不能有其他字元。 -- `fixedquery`:必須正好等於 `fixedquery`。 -- `$`:在此結束,`fixedquery` 後面不能再有其他字元。 +* `^`:以後續的字元開頭,前面不能有其他字元。 +* `fixedquery`:必須正好等於 `fixedquery`。 +* `$`:在此結束,`fixedquery` 後面不能再有其他字元。 -如果你對「正規表示式」感到困惑,別擔心。這對很多人來說都不容易。你仍然可以先不使用正規表示式就完成很多事情。 +如果你對所有這些**「正規表示式」**概念感到困惑,別擔心。這對很多人來說都不容易。你仍然可以先不使用正規表示式就完成很多事情。 -現在你知道,當你需要它們時,可以在 FastAPI 中使用它們。 +現在你知道,當你需要它們時,可以在 **FastAPI** 中使用它們。 ## 預設值 { #default-values } @@ -235,13 +236,13 @@ q: Annotated[str | None, Query(min_length=3)] = None {* ../../docs_src/query_params_str_validations/tutorial011_an_py310.py hl[9] *} -若使用這樣的 URL: +接著,若使用這樣的 URL: ``` http://localhost:8000/items/?q=foo&q=bar ``` -你會在路徑操作函式的參數 `q` 中,收到多個 `q` 查詢參數的值(`foo` 與 `bar`),以 Python 的 `list` 形式。 +你會在*路徑操作函式*的*函式參數* `q` 中,收到多個 `q` *查詢參數*的值(`foo` 與 `bar`),以 Python 的 `list` 形式。 因此,對該 URL 的回應會是: @@ -276,7 +277,7 @@ http://localhost:8000/items/?q=foo&q=bar http://localhost:8000/items/ ``` -`q` 的預設值會是:`["foo", "bar"]`,而回應會是: +`q` 的預設值會是:`["foo", "bar"]`,而你的回應會是: ```JSON { @@ -359,15 +360,15 @@ http://127.0.0.1:8000/items/?item-query=foobaritems ## 從 OpenAPI 排除參數 { #exclude-parameters-from-openapi } -若要把某個查詢參數從產生的 OpenAPI(以及自動文件系統)中排除,將 `Query` 的 `include_in_schema` 設為 `False`: +若要把某個查詢參數從產生的 OpenAPI schema(以及自動文件系統)中排除,將 `Query` 的 `include_in_schema` 設為 `False`: {* ../../docs_src/query_params_str_validations/tutorial014_an_py310.py hl[10] *} ## 自訂驗證 { #custom-validation } -有時你需要做一些上述參數無法處理的「自訂驗證」。 +有時你需要做一些上述參數無法處理的**自訂驗證**。 -這種情況下,你可以使用「自訂驗證函式」,它會在一般驗證之後套用(例如先確認值是 `str` 之後)。 +這種情況下,你可以使用**自訂驗證函式**,它會在一般驗證之後套用(例如先確認值是 `str` 之後)。 你可以在 `Annotated` 中使用 [Pydantic 的 `AfterValidator`](https://docs.pydantic.dev/latest/concepts/validators/#field-after-validator) 來達成。 @@ -389,15 +390,15 @@ Pydantic 也有 [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/va /// tip | 提示 -如果你需要做任何需要與「外部元件」溝通的驗證(例如資料庫或其他 API),應該改用「FastAPI 依賴」(FastAPI Dependencies),你稍後會學到。 +如果你需要做任何需要與**外部元件**溝通的驗證(例如資料庫或其他 API),應該改用 **FastAPI Dependencies**,你稍後會學到。 -這些自訂驗證器適用於只需使用請求中「同一份資料」即可完成的檢查。 +這些自訂驗證器適用於只需使用請求中**同一份資料**即可完成的檢查。 /// ### 理解這段程式碼 { #understand-that-code } -重點就是在 `Annotated` 中使用「`AfterValidator` 搭配函式」。如果你願意,可以略過這一節。🤸 +重點就是在 `Annotated` 中使用 **`AfterValidator` 搭配函式**。如果你願意,可以略過這一節。🤸 --- @@ -415,13 +416,13 @@ Pydantic 也有 [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/va 我們用 `list(data.items())` 把這個可疊代物件轉成正式的 `list`。 -接著用 `random.choice()` 從清單中取得一個「隨機值」,也就是一個 `(id, name)` 的 tuple。可能像是 `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`。 +接著用 `random.choice()` 從清單中取得一個**隨機值**,也就是一個 `(id, name)` 的 tuple。可能像是 `("imdb-tt0371724", "The Hitchhiker's Guide to the Galaxy")`。 -然後把這個 tuple 的兩個值分別指定給變數 `id` 和 `name`。 +然後把這個 tuple 的**兩個值分別指定**給變數 `id` 和 `name`。 因此,即使使用者沒有提供 item ID,仍然會收到一個隨機建議。 -……而這全部只用一行簡單的程式碼完成。🤯 你不愛 Python 嗎?🐍 +...而這全部只用**一行簡單的程式碼**完成。🤯 你不愛 Python 嗎?🐍 {* ../../docs_src/query_params_str_validations/tutorial015_an_py310.py ln[22:30] hl[29] *} @@ -431,16 +432,16 @@ Pydantic 也有 [`BeforeValidator`](https://docs.pydantic.dev/latest/concepts/va 通用的驗證與中繼資料: -- `alias` -- `title` -- `description` -- `deprecated` +* `alias` +* `title` +* `description` +* `deprecated` 字串專用的驗證: -- `min_length` -- `max_length` -- `pattern` +* `min_length` +* `max_length` +* `pattern` 使用 `AfterValidator` 的自訂驗證。 diff --git a/docs/zh-hant/docs/tutorial/query-params.md b/docs/zh-hant/docs/tutorial/query-params.md index 24b0cb404..86cf60a5a 100644 --- a/docs/zh-hant/docs/tutorial/query-params.md +++ b/docs/zh-hant/docs/tutorial/query-params.md @@ -67,7 +67,7 @@ http://127.0.0.1:8000/items/?skip=20 /// tip | 提示 -另外請注意,FastAPI 能辨識出路徑參數 `item_id` 是路徑參數,而 `q` 不是,因此 `q` 會被當作查詢參數。 +另外請注意,**FastAPI** 能辨識出路徑參數 `item_id` 是路徑參數,而 `q` 不是,因此 `q` 會被當作查詢參數。 /// @@ -109,9 +109,10 @@ http://127.0.0.1:8000/items/foo?short=yes 或任何其他大小寫變化(全大寫、首字母大寫等),你的函式會將參數 `short` 視為 `bool` 值 `True`。否則為 `False`。 + ## 多個路徑與查詢參數 { #multiple-path-and-query-parameters } -你可以同時宣告多個路徑參數與查詢參數,FastAPI 會自動分辨。 +你可以同時宣告多個路徑參數與查詢參數,**FastAPI** 會自動分辨。 而且不必按特定順序宣告。 diff --git a/docs/zh-hant/docs/tutorial/schema-extra-example.md b/docs/zh-hant/docs/tutorial/schema-extra-example.md index 01c4a217a..8cca5003a 100644 --- a/docs/zh-hant/docs/tutorial/schema-extra-example.md +++ b/docs/zh-hant/docs/tutorial/schema-extra-example.md @@ -10,7 +10,7 @@ {* ../../docs_src/schema_extra_example/tutorial001_py310.py hl[13:24] *} -這些額外資訊會原封不動加入該模型輸出的 JSON Schema,並且會用在 API 文件裡。 +這些額外資訊會原封不動加入該模型輸出的 **JSON Schema**,並且會用在 API 文件裡。 你可以使用屬性 `model_config`(接收一個 `dict`),詳見 [Pydantic 文件:Configuration](https://docs.pydantic.dev/latest/api/config/)。 @@ -135,7 +135,7 @@ OpenAPI 3.1.0(自 FastAPI 0.99.0 起使用)新增了對 `examples` 的支援 以下是關於 **JSON Schema** 與 **OpenAPI** 標準的技術細節。 -如果上面的做法對你已經足夠可用,就不需要這些細節,儘管直接跳過。 +如果上面的做法對你已經足夠可用,就不需要這些細節,可以直接跳過。 /// diff --git a/docs/zh-hant/docs/tutorial/security/first-steps.md b/docs/zh-hant/docs/tutorial/security/first-steps.md index b7db93b50..7640a4556 100644 --- a/docs/zh-hant/docs/tutorial/security/first-steps.md +++ b/docs/zh-hant/docs/tutorial/security/first-steps.md @@ -1,16 +1,16 @@ # 安全性 - 入門 { #security-first-steps } -想像你有一個部署在某個網域的後端 API。 +想像你有一個部署在某個網域的 **後端** API。 -還有一個前端在另一個網域,或同一網域的不同路徑(或是行動應用程式)。 +還有一個 **前端** 在另一個網域,或同一網域的不同路徑(或是行動應用程式)。 -你希望前端能用使用者名稱與密碼向後端進行身分驗證。 +你希望前端能用**使用者名稱**與**密碼**向後端進行身分驗證。 -我們可以用 OAuth2 搭配 FastAPI 來實作。 +我們可以用 **OAuth2** 搭配 **FastAPI** 來實作。 但不必通讀整份冗長規格只為了找出你需要的幾個重點。 -就用 FastAPI 提供的工具處理安全性。 +就用 **FastAPI** 提供的工具處理安全性。 ## 看起來如何 { #how-it-looks } @@ -26,7 +26,7 @@ /// note -當你使用 `pip install "fastapi[standard]"` 指令安裝時,[`python-multipart`](https://github.com/Kludex/python-multipart) 套件會隨 FastAPI 自動安裝。 +當你使用 `pip install "fastapi[standard]"` 指令安裝時,[`python-multipart`](https://github.com/Kludex/python-multipart) 套件會隨 **FastAPI** 自動安裝。 不過若只執行 `pip install fastapi`,預設不會包含 `python-multipart`。 @@ -36,7 +36,7 @@ $ pip install python-multipart ``` -因為 OAuth2 會以「form data」傳送 `username` 與 `password`。 +因為 **OAuth2** 會以「form data」傳送 `username` 與 `password`。 /// @@ -62,9 +62,9 @@ $ fastapi dev /// tip | Authorize 按鈕! -你會看到一個新的「Authorize」按鈕。 +你已經有一個亮眼的全新「Authorize」按鈕。 -而你的「路徑操作」右上角也會出現一個小鎖頭可以點擊。 +而你的 *路徑操作* 右上角也會出現一個小鎖頭可以點擊。 /// @@ -94,29 +94,29 @@ $ fastapi dev OAuth2 的設計讓後端或 API 可以獨立於執行使用者驗證的伺服器。 -但在這個例子中,同一個 FastAPI 應用會同時處理 API 與驗證。 +但在這個例子中,同一個 **FastAPI** 應用會同時處理 API 與驗證。 簡化來看流程如下: - 使用者在前端輸入 `username` 與 `password`,按下 `Enter`。 - 前端(在使用者的瀏覽器中執行)把 `username` 與 `password` 傳到我們 API 的特定 URL(在程式中宣告為 `tokenUrl="token"`)。 -- API 檢查 `username` 與 `password`,並回傳一個「token(權杖)」(我們還沒實作這部分)。 +- API 檢查 `username` 與 `password`,並回應一個「token(權杖)」(我們還沒實作這部分)。 - 「token(權杖)」就是一段字串,之後可用來識別並驗證此使用者。 - 通常 token 會設定一段時間後失效。 - 因此使用者之後需要重新登入。 - 若 token 被竊取,風險也較低;它不像永遠有效的萬用鑰匙(多數情況下)。 - 前端會暫存這個 token。 -- 使用者在前端點擊前往其他頁面/區段。 +- 使用者在前端點擊,前往前端網頁應用程式的另一個區段。 - 前端需要再向 API 取得資料。 - 但該端點需要驗證。 - 因此為了向 API 驗證,請求會帶上一個 `Authorization` 標頭,值為 `Bearer ` 加上 token。 - 例如 token 是 `foobar`,則 `Authorization` 標頭內容為:`Bearer foobar`。 -## FastAPI 的 `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } +## **FastAPI** 的 `OAuth2PasswordBearer` { #fastapis-oauth2passwordbearer } -FastAPI 提供多層抽象的工具來實作這些安全機制。 +**FastAPI** 提供多層抽象的工具來實作這些安全機制。 -本例將使用 OAuth2 的 Password 流程,並以 Bearer token 進行驗證;我們會用 `OAuth2PasswordBearer` 類別來完成。 +本例將使用 **OAuth2** 的 **Password** 流程,並以 **Bearer** token 進行驗證;我們會用 `OAuth2PasswordBearer` 類別來完成。 /// note @@ -126,7 +126,7 @@ FastAPI 提供多層抽象的工具來實作這些安全機制。 通常對多數情境也足夠,除非你是 OAuth2 專家並確信有更適合你的選項。 -在那種情況下,FastAPI 也提供相應工具讓你自行組合。 +在那種情況下,**FastAPI** 也提供相應工具讓你自行組合。 /// @@ -144,7 +144,7 @@ FastAPI 提供多層抽象的工具來實作這些安全機制。 /// -這個參數不會建立該端點/「路徑操作」,而是宣告 `/token` 將是客戶端用來取得 token 的 URL。這些資訊會出現在 OpenAPI,並被互動式 API 文件系統使用。 +這個參數不會建立該端點 / *路徑操作*,而是宣告 `/token` 將是客戶端用來取得 token 的 URL。這些資訊會出現在 OpenAPI,並被互動式 API 文件系統使用。 我們很快也會建立實際的路徑操作。 @@ -172,15 +172,15 @@ oauth2_scheme(some, parameters) {* ../../docs_src/security/tutorial001_an_py310.py hl[12] *} -此相依性會提供一個 `str`,指派給「路徑操作函式」的參數 `token`。 +此相依性會提供一個 `str`,指派給 *路徑操作函式* 的參數 `token`。 -FastAPI 會知道可以使用這個相依性,在 OpenAPI(以及自動產生的 API 文件)中定義一個「安全性方案」。 +**FastAPI** 會知道可以使用這個相依性,在 OpenAPI schema(以及自動產生的 API 文件)中定義一個「安全性方案」。 /// note | 技術細節 -FastAPI 之所以知道可以用(相依性中宣告的)`OAuth2PasswordBearer` 類別,在 OpenAPI 中定義安全性方案,是因為它繼承自 `fastapi.security.oauth2.OAuth2`,而後者又繼承自 `fastapi.security.base.SecurityBase`。 +**FastAPI** 之所以知道可以用(相依性中宣告的)`OAuth2PasswordBearer` 類別,在 OpenAPI 中定義安全性方案,是因為它繼承自 `fastapi.security.oauth2.OAuth2`,而後者又繼承自 `fastapi.security.base.SecurityBase`。 -所有能與 OpenAPI(以及自動 API 文件)整合的安全工具都繼承自 `SecurityBase`,FastAPI 才能知道如何把它們整合進 OpenAPI。 +所有能與 OpenAPI(以及自動 API 文件)整合的安全工具都繼承自 `SecurityBase`,**FastAPI** 才能知道如何把它們整合進 OpenAPI。 /// @@ -188,7 +188,7 @@ FastAPI 之所以知道可以用(相依性中宣告的)`OAuth2PasswordBearer 它會從請求中尋找 `Authorization` 標頭,檢查其值是否為 `Bearer ` 加上一段 token,並將該 token 以 `str` 回傳。 -若未找到 `Authorization` 標頭,或其值不是 `Bearer ` token,則會直接回傳 401(`UNAUTHORIZED`)錯誤。 +若未找到 `Authorization` 標頭,或其值不是 `Bearer ` token,則會直接回應 401 狀態碼錯誤(`UNAUTHORIZED`)。 你不必再自行檢查 token 是否存在;你可以確信只要你的函式被執行,該 token 參數就一定會是 `str`。 diff --git a/docs/zh-hant/docs/tutorial/security/get-current-user.md b/docs/zh-hant/docs/tutorial/security/get-current-user.md index c17b6468e..5309d78c0 100644 --- a/docs/zh-hant/docs/tutorial/security/get-current-user.md +++ b/docs/zh-hant/docs/tutorial/security/get-current-user.md @@ -14,7 +14,7 @@ 就像用 Pydantic 宣告請求體一樣,我們也可以在其他地方使用它: -{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:6] *} +{* ../../docs_src/security/tutorial002_an_py310.py hl[5,12:16] *} ## 建立 `get_current_user` 依賴 { #create-a-get-current-user-dependency } diff --git a/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md b/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md index dba108c74..dc75092b4 100644 --- a/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md +++ b/docs/zh-hant/docs/tutorial/security/oauth2-jwt.md @@ -120,7 +120,7 @@ pwdlib 也支援 bcrypt 雜湊演算法,但不包含傳統(legacy)演算 當以不存在於資料庫的使用者名稱呼叫 `authenticate_user` 時,我們仍然會拿一個假的雜湊去跑一次 `verify_password`。 -這可確保無論使用者名稱是否有效,端點的回應時間都大致相同,避免可用來枚舉既有使用者名稱的「計時攻擊」(timing attacks)。 +這可確保無論使用者名稱是否有效,端點的回應時間都大致相同,避免可用來枚舉既有使用者名稱的 **計時攻擊**(timing attacks)。 /// note | 注意 @@ -168,7 +168,7 @@ $ openssl rand -hex 32 {* ../../docs_src/security/tutorial004_an_py310.py hl[93:110] *} -## 更新 `/token` 路徑操作 { #update-the-token-path-operation } +## 更新 `/token` *路徑操作* { #update-the-token-path-operation } 用權杖有效期建立一個 `timedelta`。 diff --git a/docs/zh-hant/docs/tutorial/security/simple-oauth2.md b/docs/zh-hant/docs/tutorial/security/simple-oauth2.md index de0fe386d..2b29daa0d 100644 --- a/docs/zh-hant/docs/tutorial/security/simple-oauth2.md +++ b/docs/zh-hant/docs/tutorial/security/simple-oauth2.md @@ -132,7 +132,7 @@ OAuth2 規範中,當使用「password flow」(我們現在使用的)時, `UserInDB(**user_dict)` 的意思是: -把 `user_dict` 的鍵和值直接當作具名參數傳入,等同於: +*把 `user_dict` 的鍵和值直接當作具名參數傳入,等同於:* ```Python UserInDB( @@ -146,7 +146,7 @@ UserInDB( /// note -想更完整地了解 `**user_dict`,請回到[**額外模型** 的文件](../extra-models.md#about-user-in-dict)。 +想更完整地了解 `**user_dict`,請回到[**額外模型** 的文件](../extra-models.md#about-user-in-model-dump)。 /// diff --git a/docs/zh-hant/docs/tutorial/sql-databases.md b/docs/zh-hant/docs/tutorial/sql-databases.md index a37e16432..3a0e43d84 100644 --- a/docs/zh-hant/docs/tutorial/sql-databases.md +++ b/docs/zh-hant/docs/tutorial/sql-databases.md @@ -1,10 +1,10 @@ # SQL(關聯式)資料庫 { #sql-relational-databases } -FastAPI 不強制你使用 SQL(關聯式)資料庫。你可以使用任何你想要的資料庫。 +**FastAPI** 不強制你使用 SQL(關聯式)資料庫。但你可以使用**任何你想要的資料庫**。 這裡我們會用 [SQLModel](https://sqlmodel.tiangolo.com/) 作為範例。 -SQLModel 建立在 [SQLAlchemy](https://www.sqlalchemy.org/) 與 Pydantic 之上。它由 FastAPI 的作者開發,非常適合需要使用 SQL 資料庫的 FastAPI 應用。 +**SQLModel** 建立在 [SQLAlchemy](https://www.sqlalchemy.org/) 與 Pydantic 之上。它由 **FastAPI** 的作者開發,非常適合需要使用 **SQL 資料庫**的 FastAPI 應用。 /// tip | 提示 @@ -12,7 +12,7 @@ SQLModel 建立在 [SQLAlchemy](https://www.sqlalchemy.org/) 與 Pydantic 之上 /// -因為 SQLModel 建立在 SQLAlchemy 之上,你可以輕鬆使用 SQLAlchemy 所支援的任何資料庫(因此 SQLModel 也支援),例如: +因為 SQLModel 建立在 SQLAlchemy 之上,你可以輕鬆使用 SQLAlchemy 所支援的**任何資料庫**(因此 SQLModel 也支援),例如: * PostgreSQL * MySQL @@ -20,17 +20,17 @@ SQLModel 建立在 [SQLAlchemy](https://www.sqlalchemy.org/) 與 Pydantic 之上 * Oracle * Microsoft SQL Server,等等。 -在這個範例中,我們會使用 SQLite,因為它只用到單一檔案,而且 Python 內建支援。你可以直接複製這個範例並原樣執行。 +在這個範例中,我們會使用 **SQLite**,因為它只用到單一檔案,而且 Python 內建支援。你可以直接複製這個範例並原樣執行。 -之後,在你的正式環境應用中,你可能會想使用像 PostgreSQL 這類的資料庫伺服器。 +之後,在你的正式環境應用中,你可能會想使用像 **PostgreSQL** 這類的資料庫伺服器。 /// tip | 提示 -有一個包含 FastAPI 與 PostgreSQL 的官方專案腳手架,還有前端與更多工具:[https://github.com/fastapi/full-stack-fastapi-template](https://github.com/fastapi/full-stack-fastapi-template) +有一個包含 **FastAPI** 與 **PostgreSQL** 的官方專案產生器,還有前端與更多工具:[https://github.com/fastapi/full-stack-fastapi-template](https://github.com/fastapi/full-stack-fastapi-template) /// -這是一份非常簡短的教學,如果你想更全面學習資料庫、SQL,或更進階的功能,請參考 [SQLModel 文件](https://sqlmodel.tiangolo.com/)。 +這是一份非常簡單且簡短的教學,如果你想更全面學習資料庫、SQL,或更進階的功能,請參考 [SQLModel 文件](https://sqlmodel.tiangolo.com/)。 ## 安裝 `SQLModel` { #install-sqlmodel } @@ -47,9 +47,9 @@ $ pip install sqlmodel ## 建立只有單一模型的應用 { #create-the-app-with-a-single-model } -我們先用單一 SQLModel 模型建立這個應用的最簡版。 +我們先用單一 **SQLModel** 模型建立這個應用的最簡版。 -接著我們會在下方用多個模型來提升安全性與彈性。🤓 +接著我們會在下方用**多個模型**來提升安全性與彈性。🤓 ### 建立模型 { #create-models } @@ -57,43 +57,43 @@ $ pip install sqlmodel {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[1:11] hl[7:11] *} -`Hero` 類別與 Pydantic 模型非常相似(事實上,在底層它就是一個 Pydantic 模型)。 +`Hero` 類別與 Pydantic 模型非常相似(事實上,在底層它其實*就是一個 Pydantic 模型*)。 有幾點差異: -* `table=True` 告訴 SQLModel 這是一個「資料表模型」(table model),它應該代表 SQL 資料庫中的一個資料表,而不僅僅是「資料模型」(就像一般的 Pydantic 類別)。 +* `table=True` 告訴 SQLModel 這是一個*資料表模型*(table model),它應該代表 SQL 資料庫中的一個**資料表**,而不僅僅是*資料模型*(就像一般的 Pydantic 類別)。 -* `Field(primary_key=True)` 告訴 SQLModel,`id` 是 SQL 資料庫中的「主鍵」。 (你可以在 SQLModel 文件中進一步了解 SQL 主鍵) +* `Field(primary_key=True)` 告訴 SQLModel,`id` 是 SQL 資料庫中的**主鍵**(你可以在 SQLModel 文件中進一步了解 SQL 主鍵)。 - 注意:我們在主鍵欄位使用 `int | None`,這樣在 Python 程式碼中我們可以「在沒有 `id` 的情況下建立物件」(`id=None`),假設資料庫在儲存時會「自動產生」。SQLModel 瞭解資料庫會提供 `id`,並且在資料庫綱要中「將該欄位定義為非空的 `INTEGER`」。詳情請見 [SQLModel 文件:主鍵](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id)。 + **注意:** 我們在主鍵欄位使用 `int | None`,這樣在 Python 程式碼中我們可以*在沒有 `id` 的情況下建立物件*(`id=None`),假設資料庫在儲存時會*自動產生*。SQLModel 瞭解資料庫會提供 `id`,並且在資料庫綱要中*將該欄位定義為非空的 `INTEGER`*。詳情請見 [SQLModel 文件:主鍵](https://sqlmodel.tiangolo.com/tutorial/create-db-and-table/#primary-key-id)。 -* `Field(index=True)` 告訴 SQLModel 應為此欄位建立「SQL 索引」,以便在用此欄位過濾讀取資料時更快查詢。 +* `Field(index=True)` 告訴 SQLModel 應為此欄位建立 **SQL 索引**,以便在用此欄位過濾讀取資料時更快查詢。 SQLModel 會知道宣告為 `str` 的欄位在 SQL 中會是 `TEXT`(或 `VARCHAR`,依資料庫而定)。 ### 建立引擎 { #create-an-engine } -SQLModel 的 `engine`(底層實際上是 SQLAlchemy 的 `engine`)是用來「維護與資料庫連線」的東西。 +SQLModel 的 `engine`(底層實際上是 SQLAlchemy 的 `engine`)是用來**維護與資料庫連線**的東西。 -你的程式中應該只有「單一 `engine` 物件」來連到同一個資料庫。 +你的程式中應該只有**單一 `engine` 物件**來連到同一個資料庫。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[14:18] hl[14:15,17:18] *} -使用 `check_same_thread=False` 允許 FastAPI 在不同執行緒中使用同一個 SQLite 資料庫。這是必要的,因為「單一請求」可能會使用「多個執行緒」(例如在依賴項中)。 +使用 `check_same_thread=False` 允許 FastAPI 在不同執行緒中使用同一個 SQLite 資料庫。這是必要的,因為**單一請求**可能會使用**多個執行緒**(例如在依賴項中)。 -別擔心,依照我們的程式結構,稍後我們會確保「每個請求只使用單一 SQLModel 的 session」,這其實就是 `check_same_thread` 想要達成的事。 +別擔心,依照我們的程式結構,稍後我們會確保**每個請求只使用單一 SQLModel 的 *session***,這其實就是 `check_same_thread` 想要達成的事。 ### 建立資料表 { #create-the-tables } -接著我們新增一個函式,使用 `SQLModel.metadata.create_all(engine)` 為所有「資料表模型」建立資料表。 +接著我們新增一個函式,使用 `SQLModel.metadata.create_all(engine)` 為所有*資料表模型* **建立資料表**。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[21:22] hl[21:22] *} ### 建立 Session 依賴 { #create-a-session-dependency } -「`Session`」會在記憶體中保存物件並追蹤資料需要的任何變更,然後透過「`engine`」與資料庫溝通。 +**`Session`** 會在記憶體中保存**物件**並追蹤資料需要的任何變更,然後透過 **`engine`** 與資料庫溝通。 -我們會用 `yield` 建立一個 FastAPI 的「依賴」,為每個請求提供一個新的 `Session`。這可確保每個請求只使用單一的 session。🤓 +我們會用 `yield` 建立一個 FastAPI 的**依賴**,為每個請求提供一個新的 `Session`。這可確保每個請求只使用單一的 session。🤓 接著我們建立一個 `Annotated` 的依賴 `SessionDep`,讓後續使用這個依賴的程式碼更簡潔。 @@ -117,11 +117,11 @@ SQLModel 之後會提供包裝 Alembic 的遷移工具,但目前你可以直 ### 建立 Hero { #create-a-hero } -因為每個 SQLModel 模型同時也是一個 Pydantic 模型,你可以在「型別標註」中像使用 Pydantic 模型一樣使用它。 +因為每個 SQLModel 模型同時也是一個 Pydantic 模型,你可以在與 Pydantic 模型相同的**型別標註**中使用它。 -例如,如果你宣告一個參數型別為 `Hero`,它會從「JSON body」中讀取。 +例如,如果你宣告一個參數型別為 `Hero`,它會從 **JSON body** 中讀取。 -同樣地,你也可以將它宣告為函式的「回傳型別」,然後在自動產生的 API 文件 UI 中就會顯示其資料結構。 +同樣地,你也可以將它宣告為函式的**回傳型別**,然後在自動產生的 API 文件 UI 中就會顯示其資料結構。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[40:45] hl[40:45] *} @@ -129,19 +129,19 @@ SQLModel 之後會提供包裝 Alembic 的遷移工具,但目前你可以直 ### 讀取多個 Hero { #read-heroes } -我們可以用 `select()` 從資料庫「讀取」多個 `Hero`。可以加入 `limit` 與 `offset` 來分頁。 +我們可以用 `select()` 從資料庫**讀取**多個 `Hero`。可以加入 `limit` 與 `offset` 來分頁。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[48:55] hl[51:52,54] *} ### 讀取單一 Hero { #read-one-hero } -我們可以「讀取」單一的 `Hero`。 +我們可以**讀取**單一的 `Hero`。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[58:63] hl[60] *} ### 刪除 Hero { #delete-a-hero } -我們也可以「刪除」一個 `Hero`。 +我們也可以**刪除**一個 `Hero`。 {* ../../docs_src/sql_databases/tutorial001_an_py310.py ln[66:73] hl[71] *} @@ -159,7 +159,7 @@ $ fastapi dev
-然後前往 `/docs` 的 UI,你會看到 FastAPI 使用這些模型來「文件化」API,也會用它們來「序列化」與「驗證」資料。 +然後前往 `/docs` 的 UI,你會看到 **FastAPI** 使用這些**模型**來**文件化** API,也會用它們來**序列化**與**驗證**資料。
@@ -167,27 +167,27 @@ $ fastapi dev ## 用多個模型更新應用 { #update-the-app-with-multiple-models } -現在我們稍微「重構」一下這個應用,以提升「安全性」與「彈性」。 +現在我們稍微**重構**一下這個應用,以提升**安全性**與**彈性**。 如果你檢查前一版的應用,在 UI 中你會看到,到目前為止它讓用戶端自己決定要建立的 `Hero` 的 `id`。😱 -我們不該允許這樣,因為他們可能會覆蓋資料庫中我們已分配的 `id`。決定 `id` 應該由「後端」或「資料庫」來做,「不是用戶端」。 +我們不該允許這樣,因為他們可能會覆蓋資料庫中我們已分配的 `id`。決定 `id` 應該由**後端**或**資料庫**來做,**不是用戶端**。 -另外,我們為 hero 建立了 `secret_name`,但目前我們在各處都把它回傳出去,這一點都不「保密」... 😅 +另外,我們為 hero 建立了 `secret_name`,但目前我們在各處都把它回傳出去,這一點都不**保密**... 😅 -我們會透過加入一些「額外模型」來修正這些問題。這正是 SQLModel 大放異彩的地方。✨ +我們會透過加入一些**額外模型**來修正這些問題。這正是 SQLModel 大放異彩的地方。✨ ### 建立多個模型 { #create-multiple-models } -在 SQLModel 中,任何設了 `table=True` 的模型類別都是「資料表模型」。 +在 **SQLModel** 中,任何設了 `table=True` 的模型類別都是**資料表模型**。 -而沒有設 `table=True` 的模型類別就是「資料模型」,這些其實就是 Pydantic 模型(只有一點小增強)。🤓 +而沒有設 `table=True` 的模型類別就是**資料模型**,這些其實就是 Pydantic 模型(只有一點小增強)。🤓 -使用 SQLModel,我們可以利用「繼承」來「避免重複」在各種情況下一再宣告所有欄位。 +使用 SQLModel,我們可以利用**繼承**來**避免重複**在各種情況下一再宣告所有欄位。 #### `HeroBase` - 基底類別 { #herobase-the-base-class } -先從 `HeroBase` 模型開始,它包含所有模型「共享」的欄位: +先從 `HeroBase` 模型開始,它包含所有模型**共享**的欄位: * `name` * `age` @@ -196,12 +196,12 @@ $ fastapi dev #### `Hero` - 資料表模型 { #hero-the-table-model } -接著建立 `Hero`,也就是實際的「資料表模型」,它包含不一定會出現在其他模型中的「額外欄位」: +接著建立 `Hero`,也就是實際的*資料表模型*,它包含不一定會出現在其他模型中的**額外欄位**: * `id` * `secret_name` -因為 `Hero` 繼承自 `HeroBase`,它「也」擁有 `HeroBase` 中宣告的「欄位」,因此 `Hero` 的完整欄位為: +因為 `Hero` 繼承自 `HeroBase`,它**也**擁有 `HeroBase` 中宣告的**欄位**,因此 `Hero` 的完整欄位為: * `id` * `name` @@ -212,19 +212,19 @@ $ fastapi dev #### `HeroPublic` - 公開的資料模型 { #heropublic-the-public-data-model } -接下來建立 `HeroPublic` 模型,它是要「回傳」給 API 用戶端的模型。 +接下來建立 `HeroPublic` 模型,它是要**回傳**給 API 用戶端的模型。 它擁有與 `HeroBase` 相同的欄位,因此不會包含 `secret_name`。 終於,我們英雄的真實身分受保護了!🥷 -它也重新宣告了 `id: int`。這麼做是與 API 用戶端訂立一個「契約」,讓他們可以確定 `id` 一定存在而且是 `int`(不會是 `None`)。 +它也重新宣告了 `id: int`。這麼做是與 API 用戶端訂立一個**契約**,讓他們可以確定 `id` 一定存在而且是 `int`(不會是 `None`)。 /// tip | 提示 讓回傳模型保證某個值一定存在、而且一定是 `int`(不是 `None`),對 API 用戶端非常有幫助。他們在有這個確信下可以寫出更簡單的程式碼。 -此外,透過「自動產生的客戶端」也會有更簡潔的介面,讓要使用你 API 的開發者能有更好的開發體驗。😎 +此外,透過**自動產生的客戶端**也會有更簡潔的介面,讓要使用你 API 的開發者能有更好的開發體驗。😎 /// @@ -238,17 +238,17 @@ $ fastapi dev #### `HeroCreate` - 用於建立 Hero 的資料模型 { #herocreate-the-data-model-to-create-a-hero } -現在我們建立 `HeroCreate` 模型,這是用來「驗證」用戶端送來資料的模型。 +現在我們建立 `HeroCreate` 模型,這是用來**驗證**用戶端送來資料的模型。 它具有與 `HeroBase` 相同的欄位,並且還有 `secret_name`。 -接下來,當用戶端「建立新 hero」時,他們會送上 `secret_name`,它會被儲存在資料庫中,但這些祕密名稱不會在 API 中回傳給用戶端。 +接下來,當用戶端**建立新 hero** 時,他們會送上 `secret_name`,它會被儲存在資料庫中,但這些祕密名稱不會在 API 中回傳給用戶端。 /// tip | 提示 -這也就是你處理「密碼」的方式。接收它們,但不要在 API 中回傳。 +這也就是你處理**密碼**的方式。接收它們,但不要在 API 中回傳。 -你也應該在儲存前先對密碼做「雜湊」,「永遠不要以明文儲存」。 +你也應該在儲存前先對密碼做**雜湊**,**永遠不要以明文儲存**。 /// @@ -262,11 +262,11 @@ $ fastapi dev #### `HeroUpdate` - 用於更新 Hero 的資料模型 { #heroupdate-the-data-model-to-update-a-hero } -在前一版的應用中,我們沒有「更新 hero」的方式,但現在有了「多個模型」,我們就能做到。🎉 +在前一版的應用中,我們沒有**更新 hero** 的方式,但現在有了**多個模型**,我們就能做到。🎉 -`HeroUpdate` 這個資料模型有點特別,它包含「建立新 hero 所需的所有欄位」,但所有欄位都是「可選的」(都有預設值)。這樣在更新時,你只需要送出想要更新的欄位即可。 +`HeroUpdate` 這個*資料模型*有點特別,它包含**建立新 hero 所需的所有欄位**,但所有欄位都是**可選的**(都有預設值)。這樣在更新時,你只需要送出想要更新的欄位即可。 -因為所有欄位的「型別其實都改變了」(型別現在包含 `None`,而且預設值為 `None`),我們需要「重新宣告」它們。 +因為所有**欄位其實都改變了**(型別現在包含 `None`,而且預設值為 `None`),我們需要**重新宣告**它們。 其實不一定要繼承 `HeroBase`,因為我們會重新宣告所有欄位。我這裡保留繼承只是為了一致性,並非必要。這主要是個人偏好的問題。🤷 @@ -280,43 +280,43 @@ $ fastapi dev ### 用 `HeroCreate` 建立並回傳 `HeroPublic` { #create-with-herocreate-and-return-a-heropublic } -現在我們有了「多個模型」,可以更新應用中使用它們的部分。 +現在我們有了**多個模型**,可以更新應用中使用它們的部分。 -我們在請求中接收 `HeroCreate`(資料模型),並由它建立一個 `Hero`(資料表模型)。 +我們在請求中接收 `HeroCreate` *資料模型*,並由它建立一個 `Hero` *資料表模型*。 -這個新的資料表模型 `Hero` 會有用戶端傳來的欄位,並且會由資料庫產生一個 `id`。 +這個新的*資料表模型* `Hero` 會有用戶端傳來的欄位,並且會由資料庫產生一個 `id`。 -然後我們直接從函式回傳這個資料表模型 `Hero`。但因為我們用 `HeroPublic` 當作 `response_model`,FastAPI 會用 `HeroPublic` 來驗證與序列化資料。 +然後我們直接從函式回傳這個*資料表模型* `Hero`。但因為我們用 `HeroPublic` *資料模型*當作 `response_model`,**FastAPI** 會用 `HeroPublic` 來驗證與序列化資料。 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[56:62] hl[56:58] *} /// tip | 提示 -現在我們用 `response_model=HeroPublic`,而不是用回傳型別標註 `-> HeroPublic`,因為我們實際回傳的值其實「不是」`HeroPublic`。 +現在我們用 `response_model=HeroPublic`,而不是用**回傳型別標註** `-> HeroPublic`,因為我們實際回傳的值其實*不是* `HeroPublic`。 如果我們宣告 `-> HeroPublic`,你的編輯器與 linter 會(理所當然地)抱怨你回傳的是 `Hero` 而不是 `HeroPublic`。 -在 `response_model` 中宣告,就是要讓 FastAPI 去做它該做的事,而不影響型別標註,以及你的編輯器與其他工具提供的協助。 +在 `response_model` 中宣告,就是要讓 **FastAPI** 去做它該做的事,而不影響型別標註,以及你的編輯器與其他工具提供的協助。 /// ### 使用 `HeroPublic` 讀取多個 Hero { #read-heroes-with-heropublic } -我們可以像先前一樣「讀取」多個 `Hero`。同樣地,我們使用 `response_model=list[HeroPublic]` 來確保資料被正確驗證與序列化。 +我們可以像先前一樣**讀取**多個 `Hero`。同樣地,我們使用 `response_model=list[HeroPublic]` 來確保資料被正確驗證與序列化。 {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[65:72] hl[65] *} ### 使用 `HeroPublic` 讀取單一 Hero { #read-one-hero-with-heropublic } -我們可以「讀取」單一 hero: +我們可以**讀取**單一 hero: {* ../../docs_src/sql_databases/tutorial002_an_py310.py ln[75:80] hl[77] *} ### 使用 `HeroUpdate` 更新 Hero { #update-a-hero-with-heroupdate } -我們可以「更新 hero」。為此我們使用 HTTP 的 `PATCH` 操作。 +我們可以**更新 hero**。為此我們使用 HTTP 的 `PATCH` 操作。 -在程式碼中,我們會取得一個只包含用戶端有傳送的資料的 `dict`,不包含只是因為有預設值而存在的欄位。為了達成這點,我們使用 `exclude_unset=True`。這是關鍵。🪄 +在程式碼中,我們會取得一個只包含用戶端有傳送的資料的 `dict`,**只包含用戶端傳送的資料**,不包含只是因為有預設值而存在的欄位。為了達成這點,我們使用 `exclude_unset=True`。這是關鍵。🪄 然後我們使用 `hero_db.sqlmodel_update(hero_data)` 以 `hero_data` 的資料更新 `hero_db`。 @@ -324,7 +324,7 @@ $ fastapi dev ### 再次刪除 Hero { #delete-a-hero-again } -「刪除」 hero 基本上維持不變。 +**刪除** hero 基本上維持不變。 我們不會為了重構而重構一切。😅 @@ -352,6 +352,6 @@ $ fastapi dev ## 總結 { #recap } -你可以使用 [SQLModel](https://sqlmodel.tiangolo.com/) 與 SQL 資料庫互動,並用「資料模型」與「資料表模型」讓程式碼更簡潔。 +你可以使用 [**SQLModel**](https://sqlmodel.tiangolo.com/) 與 SQL 資料庫互動,並用*資料模型*與*資料表模型*讓程式碼更簡潔。 -你可以在 SQLModel 文件學到更多內容,這裡還有一份更長的 [使用 SQLModel 與 FastAPI 的教學](https://sqlmodel.tiangolo.com/tutorial/fastapi/)。🚀 +你可以在 **SQLModel** 文件學到更多內容,這裡還有一份更長的 [使用 SQLModel 與 **FastAPI** 的教學](https://sqlmodel.tiangolo.com/tutorial/fastapi/)。🚀 diff --git a/docs/zh-hant/docs/tutorial/static-files.md b/docs/zh-hant/docs/tutorial/static-files.md index 1b9e92a1c..0d6369eef 100644 --- a/docs/zh-hant/docs/tutorial/static-files.md +++ b/docs/zh-hant/docs/tutorial/static-files.md @@ -2,6 +2,14 @@ 你可以使用 `StaticFiles` 從某個目錄自動提供靜態檔案。 +/// tip + +如果你需要託管前端,請改用 `app.frontend()`,請在 [前端](frontend.md) 閱讀相關內容。 + +`app.frontend()` 底層使用 `StaticFiles`,並為前端提供幾項額外優勢,例如處理客戶端路由。 + +/// + ## 使用 `StaticFiles` { #use-staticfiles } - 匯入 `StaticFiles`。 diff --git a/docs/zh-hant/docs/tutorial/testing.md b/docs/zh-hant/docs/tutorial/testing.md index ab9dac93c..09f6c0ec7 100644 --- a/docs/zh-hant/docs/tutorial/testing.md +++ b/docs/zh-hant/docs/tutorial/testing.md @@ -113,13 +113,13 @@ $ pip install httpx │   └── test_main.py ``` -假設現在你的 **FastAPI** 應用所在的 `main.py` 有一些其他的路徑操作(path operations)。 +假設現在你的 **FastAPI** 應用所在的 `main.py` 有一些其他的 **路徑操作**。 它有一個可能回傳錯誤的 `GET` 操作。 它有一個可能回傳多種錯誤的 `POST` 操作。 -兩個路徑操作都需要一個 `X-Token` 標頭(header)。 +兩個 *路徑操作* 都需要一個 `X-Token` 標頭(header)。 {* ../../docs_src/app_testing/app_b_an_py310/main.py *} @@ -136,11 +136,11 @@ $ pip install httpx 例如: -* 要傳遞路徑或查詢參數,直接把它加在 URL 上。 +* 要傳遞 *path* 或 *query* 參數,直接把它加在 URL 上。 * 要傳遞 JSON 本文,將 Python 物件(例如 `dict`)傳給 `json` 參數。 -* 如果需要送出表單資料(Form Data)而不是 JSON,改用 `data` 參數。 -* 要傳遞標頭(headers),在 `headers` 參數中放一個 `dict`。 -* 對於 Cookie(cookies),在 `cookies` 參數中放一個 `dict`。 +* 如果需要送出 *Form Data* 而不是 JSON,改用 `data` 參數。 +* 要傳遞 *headers*,在 `headers` 參數中放一個 `dict`。 +* 對於 *cookies*,在 `cookies` 參數中放一個 `dict`。 關於如何把資料傳給後端(使用 `httpx` 或 `TestClient`),更多資訊請參考 [HTTPX 文件](https://www.python-httpx.org)。